Compare commits

..

61 Commits

Author SHA1 Message Date
Niels De Graef
e04cbddf92 cogl: Don't use GL_ALPHA
It was deprecated in OpenGL and it isn't even a valid value anymore for
functions like `glTextImage2D()` in OpenGL 4.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/612
2019-06-12 09:21:09 +02:00
Daniel Mustieles
d3e789e677 Updated Spanish translation 2019-06-11 12:56:38 +02:00
Pekka Paalanen
c24d8e856b clutter/x11: Fix build without libwacom
When libwacom is configured disabled, this error appears:

../clutter/clutter/x11/clutter-input-device-xi2.c: In function ‘clutter_input_device_xi2_finalize’:
../clutter/clutter/x11/clutter-input-device-xi2.c:122:7: error: ‘device_xi2’ undeclared (first use in this function)
   if (device_xi2->inhibit_pointer_query_timer)

Fix it with the "obvious" solution.

This code was added in c1303bd642.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/611
2019-06-10 14:25:05 +03:00
Daniel van Vugt
9db9793f33 clutter: Clarify clutter_stage_get_actor_at_pos docs
When a user moves their cursor the perceived behaviour is that it will
pick what is under the cursor. However this isn't how picking works.
Picking does a virtual redraw of the screen, so in some cases what gets
picked isn't the same as what the user could see on the previous frame.
It more represents what will be drawn on the next frame than what is on
screen at present.

It may be unsafe to change these semantics, and they are useful anyway.
Just document it better.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/214
2019-06-07 19:58:49 +00:00
Daniel van Vugt
c237bc5f45 clutter-effect: Rename get_paint_volume
`_clutter_effect_get_paint_volume` was misleading. Its only purpose is
to modify an existing paint volume. So change `get` to `modify`.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/115
2019-06-07 19:51:53 +00:00
Jonas Ådahl
178b975d6a cursor-renderer: Align OpenGL cursor rect to physical pixel grid
When stage views are scaled with fractional scales, the cursor rectangle
won't be aligned with the physical pixel grid, making it potentially
blurry when positioned in between physical pixels. This can be avoided
by aligning the drawn rectangle to the physical pixel grid of the stage
view the cursor is located on.

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

https://gitlab.gnome.org/GNOME/mutter/merge_requests/610
2019-06-07 19:11:34 +00:00
Jonas Ådahl
4abca411f3 clutter/stage: Expose stage view getter helper as API
Non-introspected and private to mutter, for getting a stage view from a
coordinate.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/610
2019-06-07 19:11:34 +00:00
Jonas Ådahl
e48c7c009a clutter/stage: Make view fetch helper take floats
https://gitlab.gnome.org/GNOME/mutter/merge_requests/610
2019-06-07 19:11:34 +00:00
Jonas Ådahl
36b361617d wayland/cursor-surface: Update sprite when attaching NULL
Attaching a NULL buffer should hide the cursor sprite. In these cases,
we we'll have neither surface nor buffer damage, so also update when we
just attached a NULL buffer.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/630
2019-06-07 16:06:47 +00:00
Jonas Ådahl
5eac1d696d wayland/surface: Clear texture when attaching NULL
When 252e64a0ea moved the texture
ownership to MetaWaylandSurface, it failed to handle the case when a
NULL-buffer is attached, leaving the texture reference in place. This
caused issues when the surface should have been hidden (e.g. attaching a
NULL buffer to a cursor surface for hiding the cursor sprite).

Related: https://gitlab.gnome.org/GNOME/mutter/issues/630
2019-06-07 16:06:47 +00:00
Georges Basile Stavracas Neto
9b53583945 cogl/trace: Fix typo
https://gitlab.gnome.org/GNOME/mutter/merge_requests/609
2019-06-07 12:58:10 -03:00
Georges Basile Stavracas Neto
1dbf25afa1 clutter/stage-cogl: Protect against extremely high refresh rates
After 4faeb12731, the maximum time allowed for an update to happen
is calculated as:

  max_render_time_allowed = refresh_interval - 1000 * sync_delay;

However, extremely small refresh intervals -- that come as consequence
to extremely high refresh rates -- may fall into an odd numerical range
when refresh_interval < 1000 * sync_delay. That would give us a negative
time.

To be extra cautious about it, add another sanity check for this case.

Change suggested by Jasper St. Pierre.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 12:20:49 -03:00
Daniel van Vugt
e415cc538a clutter/master-clock: Remove fallback throttles
The presentation timing logic (via `master_clock_get_swap_wait_time`) now
works unconditionally. By "works" we mean that a result of zero from
`master_clock_get_swap_wait_time` actually means zero now. Previously
zero could mean either a successful result of zero milliseconds or that
the backend couldn't get an answer. And a non-zero result is the same as
before.

This works even if the screen is "idle" and even if the backend doesn't
provide presentation timestamps. So now our two fallback throttling
mechanisms of relying on `CLUTTER_FEATURE_SWAP_THROTTLE` and decimating
to `clutter_get_default_frame_rate` can be deleted.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/406 and
        https://bugzilla.gnome.org/show_bug.cgi?id=781835

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 12:08:49 -03:00
Daniel van Vugt
67a3715ded clutter/stage-cogl: Reduce while loop iterations
If `last_presentation_time` is zero (unsupported) or just very old
(system was idle) then we would like to avoid that triggering a large
number of loop interations. This will get us closer to the right answer
without iterating.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 12:08:49 -03:00
Daniel van Vugt
35aa278194 clutter/stage-cogl: Stop schedule_update repeatedly returning now
That could happen if the backend did not provide presentation timestamps,
or if the screen was not changing other than the hardware cursor:

  if (stage_cogl->last_presentation_time == 0||
      stage_cogl->last_presentation_time < now - 150000)
    {
      stage_cogl->update_time = now;
      return;
    }

By setting `update_time` to `now`, master_clock_get_swap_wait_time()
returns 0:

  gint64 now = g_source_get_time (master_clock->source);
  if (min_update_time < now)
    {
      return 0;
    }
  else
    {
      gint64 delay_us = min_update_time - now;
      return (delay_us + 999) / 1000;
    }

However, zero is a value unsupported by the default master clock
due to:

  if (swap_delay != 0)
    return swap_delay;

All cases are now handled by extrapolating when the next presentation
time would be and calculating an appropriate update time to meet that.

We also need to add a check for `update_time == last_update_time`, which
is a situation that just became possible since we support old (or zero)
values of `last_presentation_time`. This avoids getting more than one
stage update per frame interval when input events arrive without
triggering a stage redraw (e.g. moving the hardware cursor).

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 12:03:35 -03:00
Daniel van Vugt
a76762a05e clutter/stage-cogl: Use default frame rate instead of hardcoded 60Hz
Instead of 0Hz falling back to 60Hz, use `CLUTTER_DEFAULT_FPS` which is
also 60Hz by default.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 14:42:01 +08:00
Daniel van Vugt
ccf27e5f83 clutter/stage-cogl: Schedule immediate update on zero refresh interval
Instead of crazy refresh rates >1MHz falling back to 60Hz, just honour
them by rendering unthrottled (same as `sync_delay < 0`). Although I
wouldn't actually expect that path to ever be needed in reality, it just
ensures an infinite `while` loop never happens.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 14:42:01 +08:00
Daniel van Vugt
912a9ecfba clutter/stage-cogl: Use G_USEC_PER_SEC instead of hardcoded number
One million is the number of microseconds in one second, which is also
defined by `G_USEC_PER_SEC`.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/363
2019-06-07 14:42:01 +08:00
Marco Trevisan (Treviño)
0487d672ed x11-display: Handle mapped XIDs per type
Starting from commit 7713006f5, during X11 disposition we also unmanage the
windows using the xids hash table values list.
However, this is also populated by the X11 Meta barrier implementation and then
contains both Windows and Barriers.

So when going through the values list, check whether we're handling a window or
a barrier and based on that, unmanage or destroy it.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/624
https://gitlab.gnome.org/GNOME/mutter/merge_requests/605
2019-06-06 21:35:11 +00:00
Marco Trevisan (Treviño)
e94a0fced9 display: Dispose Stack after Compositor and X11
As per commit 7718e67f, destroying the compositor causes destroying window
actors and this leads to stack changes, but at this point the stack was already
disposed and cleared.

So, clear the stack when any component that could use it (compositor, and X11)
has already been destroyed.
As consequence, also the stamps should be destroyed at later point.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/623
https://gitlab.gnome.org/GNOME/mutter/merge_requests/605
2019-06-06 21:35:11 +00:00
Olivier Fourdan
a3b86447f7 backends: Add mouse accessibility settings
Add support for mouse accessibility settings to set the click assist
values.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
1d76eace1e clutter: Hook up pointer accessibility
When using evdev (for Wayland), the backend receives all device events
and queue them for clutter.

Hook up the pointer accessibility handlers in clutter's main processing
queue, so that we get better accuracy for pointer location.

We need to avoid doing this on X11 though because X11 relies on the raw
events for this to work reliably, so the same is already done in the
X11 backend when using X11.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
c1303bd642 clutter/x11: Hook up pointer accessibility
Pointer accessibility features requires to receive all pointer events
regardless of X11 grabs.

Add XI2 raw events mask and hook up the pointer accessibility handlers
to the raw motion and button press/release events.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
db11a37a68 clutter: Add pointer accessibility features
Add support for click assist, namely simulated secondary click (on a
long primary button press) and hover click support (simulate a click when
the pointer remains static for some time).

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
0d0b9da6f8 clutter: Add pointer accessibility signals
Add the required signaling in place in clutter device manager to notify
the upper layers (namely, the shell) whenever a click assist delay or
gesture is started or stopped.

This will allow the shell to implement a visual feedback for click
assist operations.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
ab0b407da4 clutter/enums: Add pointer accessibility types
Add the relevant enumeration types to support pointer accessibility
features.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
c33b330799 backends: Rename keyboard accessibility settings
Naming the keyboard accessibility settings `a11y_settings` wrongly
assumes there will never be any other type of accessibility settings.

Rename `a11y_settings` to `keyboard_a11y_settings` to avoid future
confusion.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
144b24bfcc clutter/evdev: Use the accessibility virtual device
Instead of adding one specifically for keyboard accessibility in evdev,
use the one from ClutterInputDevice instead.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Olivier Fourdan
4d21650d6d clutter: Add an accessibility virtual device
For accessibility features, being either keyboard accessibility to
implement mousekeys, or pointer accessibility to implement simulated
secondary click or dwell click, we need to have a virtual device.

Add that virtual device in ClutterInputDevice so it can be used either
for keyboard or pointer accessibility.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/512
2019-06-06 13:04:50 +02:00
Marco Trevisan (Treviño)
a6fc656e91 window: Emit an error and return when trying to activate an unmanaged
If something (i.e. gnome-shell or an extension) tries to activate an unmanaged
window, we should warn about this and avoid to perform further actions as this
could lead to a crash of mutter, since the window has not valid flags (like
workspace) set anymore at this stage.

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

https://gitlab.gnome.org/GNOME/mutter/merge_requests/564
2019-06-05 17:53:12 +00:00
Douglas R. Reno
a38bae259e docs: Update tests instructions
The documentation still refers to autotools, update it to
use the corresponding meson commands.

https://gitlab.gnome.org/GNOME/mutter/issues/568
2019-06-05 14:49:35 -03:00
Olivier Fourdan
c53aa89098 keybindings: Small code cleanup
Reuse the name we just set to insert in the hash table, that avoids
duplicating the string.

Suggested-by: Carlos Garnacho <carlosg@gnome.org>

https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
2019-06-05 09:34:39 +00:00
Olivier Fourdan
851b7d0639 keybindings: Trigger locate-pointer on key modifier
We trigger the "locate-pointer" mechanism when a special key modifier
(defaults to Control_L) key is pressed and released.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
https://gitlab.gnome.org/GNOME/gnome-shell/issues/981
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/merge_requests/19
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/86
2019-06-05 09:34:39 +00:00
Olivier Fourdan
b4c78726cf compositor: Add "locate_pointer" vmethod
This method is invoked to locate the pointer on screen.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
https://gitlab.gnome.org/GNOME/gnome-shell/issues/981
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/merge_requests/19
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/86
2019-06-05 09:34:39 +00:00
Olivier Fourdan
c9cc07fd3a settings: Slack off “xwayland-allow-grabs” setting
To emulate X11 grabs, mutter as a Wayland compositor would disable its
own keyboard shortcuts and when the X11 window is an override redirect
window (which never receives focus), it also forces keyboard focus onto
that X11 O-R window so that all keyboard events are routed to the
window, just like an X11 server would.

But that's a bit of a “all-or-nothing” approach which prevents
applications that would legitimately grab the keyboard under X11 (like
virtual machine viewers) to work by default.

Change “xwayland-allow-grabs” to control whether the keyboard focus
should be locked onto override redirect windows in case of an X11 grab.

For stringent needs, careful users can still use the blacklisting
feature (i.e. a list containing “!*”) to prevent grabs from any X11
applications to affect other Wayland native applications.

https://gitlab.gnome.org/GNOME/mutter/issues/597
2019-06-03 09:34:31 +02:00
Olivier Fourdan
f6eb2a8cf8 settings: Remove space characters
Small code style cleanup.

https://gitlab.gnome.org/GNOME/mutter/issues/597
2019-06-03 09:34:31 +02:00
Balázs Úr
08e5589836 Update Hungarian translation 2019-06-01 15:48:01 +00:00
Piotr Drąg
4f5a5e84fc Update POTFILES.in 2019-05-31 20:47:46 +02:00
Robert Mader
0786683189 meson: Add no-omit-frame-pointer to clutter debug builds
This will help us getting better stacktraces and sysprof integration.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/601
2019-05-31 16:03:43 +00:00
Robert Mader
4887de533c meson: Do not use clutter_c_args for GIR
Certain arguments like `-fno-omit-frame-pointer` break GIR creation.
Lets handle this like we do for the rest of mutter and duplicate the
relevant arguments from `clutter_c_args`.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/601
2019-05-31 16:03:43 +00:00
Georges Basile Stavracas Neto
57945a730f backend: Conditionally compile MetaProfiler
MetaProfiler is not built when -Dprofiler=false, and that
breaks the build since MetaBackend unconditionally imports
and uses it.

Fix that by wrapping MetaProfiler in compile-time checks.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/603
2019-05-31 12:54:13 -03:00
Georges Basile Stavracas Neto
78254146f3 build: Rename HAVE_TRACING to HAVE_PROFILER in Mutter
It fits better the name of the build flag. Cogl still uses
HAVE_TRACING since profiler is already used by it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/603
2019-05-31 12:54:10 -03:00
Georges Basile Stavracas Neto
3e2a2cf532 clutter/stage-cogl: Simplify redraw function
Spotted while adding tracing to swap buffers, we only enter
the first part of the if condition when use_clipped_redraw
is TRUE, so it's pretty safe to assume it's TRUE.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:09 -03:00
Georges Basile Stavracas Neto
04b240b50c ci: Add sysprof3 to the Docker image
It is now a dependency that we want to build against,
even if optional.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:09 -03:00
Georges Basile Stavracas Neto
7810f0e276 cogl/trace: Add user-visible group name
This way, it shows up as "Compositor" in Sysprof instead of
"t:XYZ".

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:09 -03:00
Georges Basile Stavracas Neto
9b8f9b65b8 clutter: Add more descriptive profiling sections
The idea here is to be able to visualize and immediately
understand what is happening. Something like:

```
                   [ view1 ] [ view2 ]
 [---- Layout ---][------ Paint ------][ Pick ]
[================== Update =====================]
```

But with colors. A few of the previous profiling data
sections were removed, since they didn't really add to
reading the graph.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:08 -03:00
Georges Basile Stavracas Neto
e741cab3f4 profiler: Support setting output filename
So we can have some control over where the file will
be saved.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:08 -03:00
Georges Basile Stavracas Neto
53748e3da7 cogl-trace: Cleanup context after disabling
This allows running the Capture() method multiple times,
with different arguments each time.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:07 -03:00
Georges Basile Stavracas Neto
17c5436f6e profile: Add a Sysprof-based profiler
This exposes the /org/gnome/Sysprof3/Profiler object
inside Mutter to allow initiating a Sysprof capture.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:07 -03:00
Jonas Ådahl
04fb6f7659 clutter: Add some preliminary tracing to clutter
https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:57:07 -03:00
Jonas Ådahl
e5e58f8075 cogl: Add libsysprof capture based tracing
Add the ability to add tracing instrumentation to the code. When
enabled, trace entries will generate a file with timing information
that will be processable by sysprof for generating visualization of
traces over time.

While enabled by default at compile time, it is possible to disable the
expansion of the macros completely by passing --disable-tracing to
./configure.

Tracing is so far only actually done if actually enabled on explicitly
specified threads.

This will be used by Mutter passing the write end of a pipe, where the
read end is sent to Sysprof itself via the D-Bus method 'Capture()'.

By passing that, we have to detect EPIPE that is sent when Sysprof stops
recording. Fortunately, we already ignore the signal at meta_init(), so
no need to add a custom signal handler.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/197
2019-05-31 11:55:56 -03:00
Carlos Garnacho
1da0355528 wayland: Update tablet cursor outputs across cursor/proximity changes
Make sure those generic surface events are sent early on when setting a
cursor for any tablet tool, so clients can update to output characteristics.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/545
Related: https://gitlab.gnome.org/GNOME/gtk/issues/1675
2019-05-31 09:57:24 +00:00
Carlos Garnacho
e5881156f6 wayland: Handle NULL cursor renderer finding the outputs of a cursor role
Having a cursor role with a NULL renderer is valid state, and even desirable
on tablets (eg. after proximity out). In those cases it should be
interpreted as the cursor surface not being over any output.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/545
2019-05-31 09:57:24 +00:00
Marco Trevisan (Treviño)
60170cff70 compositor: Emit 'grab-op-end' signal after ungrab happened
We're currently emitting the 'grab-op-end' signal when the grab prerequisites
are met, but when display->grab_op is still set to a not-NONE value and thus
meta_display_get_grab_op() would return that in the signal callback.
And more importantly when this is emitted, devices are still grabbed.

Instead, emit this signal as soon as we've unset all the grab properties and
released the devices.

Helps with https://gitlab.gnome.org/GNOME/gnome-shell/issues/1326

https://gitlab.gnome.org/GNOME/mutter/merge_requests/596
2019-05-29 20:09:40 +00:00
Marco Trevisan (Treviño)
e2bea48073 display: Emit 'grab-op-end' signal after ungrab happened
We're currently emitting the 'grab-op-end' signal when the grab prerequisites
are met, but when display->grab_op is still set to a not-NONE value and thus
meta_display_get_grab_op() would return that in the signal callback.
And more importantly when this is emitted, devices are still grabbed.

Instead, emit this signal as soon as we've unset all the grab properties and
released the devices.

Helps with https://gitlab.gnome.org/GNOME/gnome-shell/issues/1326

https://gitlab.gnome.org/GNOME/mutter/merge_requests/596
2019-05-29 20:09:40 +00:00
Carlos Garnacho
bbfaf8204b wayland: Honor startup sequence workspace on .request_focus
We handle this in backend specific code for x11, so do the wayland
bits here. We can only honor this on applications that request focus
on a surface after a startup request, as we do need an explicit
surface to apply the workspace on (and we don't have additional clues
like WMCLASS on X11). Notably, gtk_shell1.notify_startup doesn't suffice.

Another gotcha is that the .request_focus happens when the surface is
already "mapped". Due to the way x11 and the GDK api currently work (first
reply on the startup id, then map a window, then request focus on that
window). This means the surface will ignore at this point
window->initial_workspace, so it must be actively changed.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/544
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/674
2019-05-29 16:21:15 +00:00
Carlos Garnacho
b3e19ee669 wayland: Unset DnD selection on wl_data_offer destruction
On a successful DnD operation we may expect the wl_data_source and
wl_data_offer to live long enough to finish the data transfer, despite the
grab operation (and other supporting data) being gone.

When that happens, the compositor expects a wl_data_offer.finish request to
notify that it finished. However the client may still chose not to send that
and destroy the wl_data_offer instead, resulting in the MetaSelectionSource
owner for the DnD selection not being unset.

When that happens, the DnD MetaSelectionSource still exists but it's
detached from any grab operation, so will not be unset if eg. the drag
source client destroys the wl_data_source. This may result in crashes when
the next drag operation tries to replace the owner DnD MetaSelectionSource.

Check explicitly for this case, in order to ensure the DnD owner is unset
after such operations.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/591
2019-05-29 16:10:57 +00:00
Robert Mader
75e2bfb062 meson: Do not add compiler flags if 'plain' buildtype is used
That is how the 'plain' buildtype is meant in meson.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/497
2019-05-29 15:52:39 +00:00
Robert Mader
a859d76c72 meson: Cleanup debug build handling
Add debug flags based on meson's `debug` option instead of `buildtype`.
This allows custom build configurations to behave like a debug or release build.

Add `-fno-omit-frame-pointer` to Mutter/Cogl. Not to Clutter though, as that would
require more changes to how Clutter's gir is created

Remove `-DG_DISABLE_CAST_CHECKS` from Clutter in debug builds

Add `-DG_DISABLE_CHECKS`, `-DG_DISABLE_ASSERT` and `-DG_DISABLE_CAST_CHECKS` to all
non-debug builds but `plain`, which explicitly should not have any compile flags

Use `cc.get_supported_arguments`, so it becomes more obvious to the user which flags
are set during compilation

https://gitlab.gnome.org/GNOME/mutter/merge_requests/497
2019-05-29 15:52:39 +00:00
Pekka Paalanen
2145333969 renderer/native: Refactor into secondary_gpu_get_next_dumb_buffer
Extract the next buffer -logic into a new function. This allows to
simplify copy_shared_framebuffer_cpu () making it more readable.

This change is a pure refactoring, no functional changes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/593
2019-05-29 11:53:00 -03:00
Robert Mader
1b61b9cd73 boxes: Fix calculation of rounded rectangles
Since 68fba458 the function is used for more calculations, exposing
a bug when used with fractional scaling.

https://gitlab.gnome.org/GNOME/mutter/issues/609
2019-05-29 00:07:15 +02:00
75 changed files with 2793 additions and 565 deletions

View File

@@ -15,6 +15,7 @@ RUN dnf -y update && dnf -y upgrade && \
# Unpackaged versions
dnf install -y https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00834984-gsettings-desktop-schemas/gsettings-desktop-schemas-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00834984-gsettings-desktop-schemas/gsettings-desktop-schemas-devel-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm && \
dnf install -y https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/libsysprof-ui-3.33.2-1.fc30.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/sysprof-cli-3.33.2-1.fc30.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/sysprof-3.33.2-1.fc30.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/sysprof-devel-3.33.2-1.fc30.x86_64.rpm && \
dnf install -y intltool redhat-rpm-config make && \

View File

@@ -17551,7 +17551,7 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self,
l != NULL && l->data != priv->current_effect;
l = l->next)
{
if (!_clutter_effect_get_paint_volume (l->data, pv))
if (!_clutter_effect_modify_paint_volume (l->data, pv))
{
clutter_paint_volume_free (pv);
CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): "
@@ -17569,7 +17569,7 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self,
/* otherwise, get the cumulative volume */
effects = _clutter_meta_group_peek_metas (priv->effects);
for (l = effects; l != NULL; l = l->next)
if (!_clutter_effect_get_paint_volume (l->data, pv))
if (!_clutter_effect_modify_paint_volume (l->data, pv))
{
clutter_paint_volume_free (pv);
CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): "

View File

@@ -178,8 +178,8 @@ clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect)
}
static gboolean
clutter_blur_effect_get_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
clutter_blur_effect_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
{
gfloat cur_width, cur_height;
ClutterVertex origin;
@@ -223,7 +223,7 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass)
gobject_class->dispose = clutter_blur_effect_dispose;
effect_class->pre_paint = clutter_blur_effect_pre_paint;
effect_class->get_paint_volume = clutter_blur_effect_get_paint_volume;
effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->paint_target = clutter_blur_effect_paint_target;

View File

@@ -69,6 +69,22 @@ typedef struct _ClutterTouchInfo
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 secondary_click_timer;
gboolean secondary_click_triggered;
} ClutterPtrA11yData;
struct _ClutterInputDevice
{
GObject parent_instance;
@@ -143,6 +159,10 @@ struct _ClutterInputDevice
guint has_cursor : 1;
guint is_enabled : 1;
/* Accessiblity */
ClutterVirtualInputDevice *accessibility_virtual_device;
ClutterPtrA11yData *ptr_a11y_data;
};
typedef void (*ClutterEmitInputDeviceEvent) (ClutterEvent *event,

View File

@@ -47,6 +47,7 @@
#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
{
@@ -55,6 +56,8 @@ struct _ClutterDeviceManagerPrivate
/* Keyboard a11y */
ClutterKbdA11ySettings kbd_a11y_settings;
/* Pointer a11y */
ClutterPointerA11ySettings pointer_a11y_settings;
};
enum
@@ -75,6 +78,9 @@ enum
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
};
@@ -239,6 +245,67 @@ clutter_device_manager_class_init (ClutterDeviceManagerClass *klass)
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
*
* 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,
G_TYPE_NONE, 2,
CLUTTER_TYPE_INPUT_DEVICE,
CLUTTER_TYPE_POINTER_A11Y_TIMEOUT_TYPE);
}
static void
@@ -579,3 +646,88 @@ clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager *device_man
*settings = device_manager->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)
{
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
if (are_pointer_a11y_settings_equal (&device_manager->priv->pointer_a11y_settings, settings))
return;
if (device_manager->priv->pointer_a11y_settings.controls == 0 && settings->controls != 0)
clutter_device_manager_enable_pointer_a11y (device_manager);
else if (device_manager->priv->pointer_a11y_settings.controls != 0 && settings->controls == 0)
clutter_device_manager_disable_pointer_a11y (device_manager);
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)
{
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
*settings = device_manager->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)
{
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
device_manager->priv->pointer_a11y_settings.dwell_click_type = click_type;
}

View File

@@ -73,6 +73,27 @@ typedef struct _ClutterKbdA11ySettings
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;
/**
* ClutterDeviceManager:
*
@@ -152,10 +173,23 @@ ClutterVirtualDeviceType clutter_device_manager_get_supported_virtual_device_typ
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__ */

View File

@@ -7,7 +7,7 @@ G_BEGIN_DECLS
gboolean _clutter_effect_pre_paint (ClutterEffect *effect);
void _clutter_effect_post_paint (ClutterEffect *effect);
gboolean _clutter_effect_get_paint_volume (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,

View File

@@ -188,8 +188,8 @@ clutter_effect_real_post_paint (ClutterEffect *effect)
}
static gboolean
clutter_effect_real_get_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
{
return TRUE;
}
@@ -252,7 +252,7 @@ clutter_effect_class_init (ClutterEffectClass *klass)
klass->pre_paint = clutter_effect_real_pre_paint;
klass->post_paint = clutter_effect_real_post_paint;
klass->get_paint_volume = clutter_effect_real_get_paint_volume;
klass->modify_paint_volume = clutter_effect_real_modify_paint_volume;
klass->paint = clutter_effect_real_paint;
klass->pick = clutter_effect_real_pick;
}
@@ -297,13 +297,14 @@ _clutter_effect_pick (ClutterEffect *effect,
}
gboolean
_clutter_effect_get_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
_clutter_effect_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
{
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
g_return_val_if_fail (volume != NULL, FALSE);
return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume (effect, volume);
return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume (effect,
volume);
}
gboolean
@@ -311,7 +312,7 @@ _clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
{
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume != clutter_effect_real_get_paint_volume;
return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume != clutter_effect_real_modify_paint_volume;
}
/**

View File

@@ -60,7 +60,7 @@ struct _ClutterEffect
* ClutterEffectClass:
* @pre_paint: virtual function
* @post_paint: virtual function
* @get_paint_volume: virtual function
* @modify_paint_volume: virtual function
* @paint: virtual function
* @pick: virtual function
*
@@ -74,16 +74,16 @@ struct _ClutterEffectClass
ClutterActorMetaClass parent_class;
/*< public >*/
gboolean (* pre_paint) (ClutterEffect *effect);
void (* post_paint) (ClutterEffect *effect);
gboolean (* pre_paint) (ClutterEffect *effect);
void (* post_paint) (ClutterEffect *effect);
gboolean (* get_paint_volume) (ClutterEffect *effect,
ClutterPaintVolume *volume);
gboolean (* modify_paint_volume) (ClutterEffect *effect,
ClutterPaintVolume *volume);
void (* paint) (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
void (* pick) (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
void (* paint) (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
void (* pick) (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
/*< private >*/
void (* _clutter_effect4) (void);

View File

@@ -443,6 +443,88 @@ typedef enum
CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13,
} ClutterKeyboardA11yFlags;
/**
* ClutterPointerA11yFlags:
* @CLUTTER_A11Y_POINTER_ENABLED:
* @CLUTTER_A11Y_SECONDARY_CLICK_ENABLED:
* @CLUTTER_A11Y_DWELL_ENABLED:
*
* Pointer accessibility features applied to a ClutterInputDevice pointer.
*
*/
typedef enum {
CLUTTER_A11Y_SECONDARY_CLICK_ENABLED = 1 << 0,
CLUTTER_A11Y_DWELL_ENABLED = 1 << 1,
} ClutterPointerA11yFlags;
/**
* ClutterPointerA11yDwellClickType:
* @CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE: Internal use only
* @CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY:
* @CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY:
* @CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE:
* @CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE:
* @CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG:
*
* Dwell click types.
*
*/
typedef enum {
CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE,
CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY,
CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY,
CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE,
CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE,
CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG,
} ClutterPointerA11yDwellClickType;
/**
* ClutterPointerA11yDwellDirection:
* @CLUTTER_A11Y_DWELL_DIRECTION_NONE:
* @CLUTTER_A11Y_DWELL_DIRECTION_LEFT:
* @CLUTTER_A11Y_DWELL_DIRECTION_RIGHT:
* @CLUTTER_A11Y_DWELL_DIRECTION_UP:
* @CLUTTER_A11Y_DWELL_DIRECTION_DOWN:
*
* Dwell gesture directions.
*
*/
typedef enum {
CLUTTER_A11Y_DWELL_DIRECTION_NONE,
CLUTTER_A11Y_DWELL_DIRECTION_LEFT,
CLUTTER_A11Y_DWELL_DIRECTION_RIGHT,
CLUTTER_A11Y_DWELL_DIRECTION_UP,
CLUTTER_A11Y_DWELL_DIRECTION_DOWN,
} ClutterPointerA11yDwellDirection;
/**
* ClutterPointerA11yDwellMode:
* @CLUTTER_A11Y_DWELL_MODE_WINDOW:
* @CLUTTER_A11Y_DWELL_MODE_GESTURE:
*
* Dwell mode.
*
*/
typedef enum {
CLUTTER_A11Y_DWELL_MODE_WINDOW,
CLUTTER_A11Y_DWELL_MODE_GESTURE,
} ClutterPointerA11yDwellMode;
/**
* ClutterPointerA11yTimeoutType:
* @CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK:
* @CLUTTER_A11Y_TIMEOUT_TYPE_DWELL:
* @CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE:
*
* Pointer accessibility timeout type.
*
*/
typedef enum {
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE,
} ClutterPointerA11yTimeoutType;
/**
* ClutterActorFlags:
* @CLUTTER_ACTOR_MAPPED: the actor will be painted (is visible, and inside

View File

@@ -107,6 +107,9 @@ clutter_input_device_dispose (GObject *gobject)
device->associated = NULL;
}
if (device->accessibility_virtual_device)
g_clear_object (&device->accessibility_virtual_device);
g_clear_pointer (&device->axes, g_array_unref);
g_clear_pointer (&device->keys, g_array_unref);
g_clear_pointer (&device->scroll_info, g_array_unref);

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2019 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Olivier Fourdan <ofourdan@redhat.com>
*/
#ifndef __CLUTTER_INPUT_POINTER_A11Y_H__
#define __CLUTTER_INPUT_POINTER_A11Y_H__
#include <clutter/clutter-types.h>
#include "clutter-enum-types.h"
G_BEGIN_DECLS
void _clutter_input_pointer_a11y_add_device (ClutterInputDevice *device);
void _clutter_input_pointer_a11y_remove_device (ClutterInputDevice *device);
void _clutter_input_pointer_a11y_on_motion_event (ClutterInputDevice *device,
float x,
float y);
void _clutter_input_pointer_a11y_on_button_event (ClutterInputDevice *device,
int button,
gboolean pressed);
gboolean _clutter_is_input_pointer_a11y_enabled (ClutterInputDevice *device);
G_END_DECLS
#endif /* __CLUTTER_INPUT_POINTER_A11Y_H__ */

View File

@@ -0,0 +1,669 @@
/*
* Copyright (C) 2019 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Olivier Fourdan <ofourdan@redhat.com>
*
* This reimplements in Clutter the same behavior as mousetweaks original
* implementation by Gerd Kohlberger <gerdko gmail com>
* mousetweaks Copyright (C) 2007-2010 Gerd Kohlberger <gerdko gmail com>
*/
#include "clutter-build-config.h"
#include "clutter-device-manager.h"
#include "clutter-device-manager-private.h"
#include "clutter-enum-types.h"
#include "clutter-input-device.h"
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-main.h"
#include "clutter-virtual-input-device.h"
static gboolean
is_secondary_click_enabled (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
return (settings.controls & CLUTTER_A11Y_SECONDARY_CLICK_ENABLED);
}
static gboolean
is_dwell_click_enabled (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
return (settings.controls & CLUTTER_A11Y_DWELL_ENABLED);
}
static unsigned int
get_secondary_click_delay (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
return settings.secondary_click_delay;
}
static unsigned int
get_dwell_delay (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
return settings.dwell_delay;
}
static unsigned int
get_dwell_threshold (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
return settings.dwell_threshold;
}
static ClutterPointerA11yDwellMode
get_dwell_mode (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
return settings.dwell_mode;
}
static ClutterPointerA11yDwellClickType
get_dwell_click_type (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
#
return settings.dwell_click_type;
}
static ClutterPointerA11yDwellClickType
get_dwell_click_type_for_direction (ClutterInputDevice *device,
ClutterPointerA11yDwellDirection direction)
{
ClutterPointerA11ySettings settings;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
if (direction == settings.dwell_gesture_single)
return CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY;
else if (direction == settings.dwell_gesture_double)
return CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE;
else if (direction == settings.dwell_gesture_drag)
return CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG;
else if (direction == settings.dwell_gesture_secondary)
return CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY;
return CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE;
}
static void
emit_button_press (ClutterInputDevice *device,
gint button)
{
clutter_virtual_input_device_notify_button (device->accessibility_virtual_device,
g_get_monotonic_time (),
button,
CLUTTER_BUTTON_STATE_PRESSED);
}
static void
emit_button_release (ClutterInputDevice *device,
gint button)
{
clutter_virtual_input_device_notify_button (device->accessibility_virtual_device,
g_get_monotonic_time (),
button,
CLUTTER_BUTTON_STATE_RELEASED);
}
static void
emit_button_click (ClutterInputDevice *device,
gint button)
{
emit_button_press (device, button);
emit_button_release (device, button);
}
static void
restore_dwell_position (ClutterInputDevice *device)
{
clutter_virtual_input_device_notify_absolute_motion (device->accessibility_virtual_device,
g_get_monotonic_time (),
device->ptr_a11y_data->dwell_x,
device->ptr_a11y_data->dwell_y);
}
static gboolean
trigger_secondary_click (gpointer data)
{
ClutterInputDevice *device = data;
device->ptr_a11y_data->secondary_click_triggered = TRUE;
device->ptr_a11y_data->secondary_click_timer = 0;
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-stopped",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK);
return G_SOURCE_REMOVE;
}
static void
start_secondary_click_timeout (ClutterInputDevice *device)
{
unsigned int delay = get_secondary_click_delay (device);
device->ptr_a11y_data->secondary_click_timer =
clutter_threads_add_timeout (delay, trigger_secondary_click, device);
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-started",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
delay);
}
static void
stop_secondary_click_timeout (ClutterInputDevice *device)
{
if (device->ptr_a11y_data->secondary_click_timer)
{
g_source_remove (device->ptr_a11y_data->secondary_click_timer);
device->ptr_a11y_data->secondary_click_timer = 0;
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-stopped",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK);
}
device->ptr_a11y_data->secondary_click_triggered = FALSE;
}
static gboolean
pointer_has_moved (ClutterInputDevice *device)
{
float dx, dy;
gint threshold;
dx = device->ptr_a11y_data->dwell_x - device->ptr_a11y_data->current_x;
dy = device->ptr_a11y_data->dwell_y - device->ptr_a11y_data->current_y;
threshold = get_dwell_threshold (device);
/* Pythagorean theorem */
return ((dx * dx) + (dy * dy)) > (threshold * threshold);
}
static gboolean
is_secondary_click_pending (ClutterInputDevice *device)
{
return device->ptr_a11y_data->secondary_click_timer != 0;
}
static gboolean
is_secondary_click_triggered (ClutterInputDevice *device)
{
return device->ptr_a11y_data->secondary_click_triggered;
}
static gboolean
is_dwell_click_pending (ClutterInputDevice *device)
{
return device->ptr_a11y_data->dwell_timer != 0;
}
static gboolean
is_dwell_dragging (ClutterInputDevice *device)
{
return device->ptr_a11y_data->dwell_drag_started;
}
static gboolean
is_dwell_gesturing (ClutterInputDevice *device)
{
return device->ptr_a11y_data->dwell_gesture_started;
}
static gboolean
has_button_pressed (ClutterInputDevice *device)
{
return device->ptr_a11y_data->n_btn_pressed > 0;
}
static gboolean
should_start_secondary_click_timeout (ClutterInputDevice *device)
{
return !is_dwell_dragging (device);
}
static gboolean
should_start_dwell (ClutterInputDevice *device)
{
/* We should trigger a dwell if we've not already started one, and if
* no button is currently pressed or we are in the middle of a dwell
* drag action.
*/
return !is_dwell_click_pending (device) &&
(is_dwell_dragging (device) ||
!has_button_pressed (device));
}
static gboolean
should_stop_dwell (ClutterInputDevice *device)
{
/* We should stop a dwell if the motion exceeds the threshold, unless
* we've started a gesture, because we want to keep the original dwell
* location to both detect a gesture and restore the original pointer
* location once the gesture is finished.
*/
return pointer_has_moved (device) &&
!is_dwell_gesturing (device);
}
static gboolean
should_update_dwell_position (ClutterInputDevice *device)
{
return !is_dwell_gesturing (device) &&
!is_dwell_click_pending (device) &&
!is_secondary_click_pending (device);
}
static void
update_dwell_click_type (ClutterInputDevice *device)
{
ClutterPointerA11ySettings settings;
ClutterPointerA11yDwellClickType dwell_click_type;
clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings);
dwell_click_type = settings.dwell_click_type;
switch (dwell_click_type)
{
case CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE:
case CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY:
case CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE:
dwell_click_type = CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY;
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG:
if (!is_dwell_dragging (device))
dwell_click_type = CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY;
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY:
case CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE:
default:
break;
}
if (dwell_click_type != settings.dwell_click_type)
{
settings.dwell_click_type = dwell_click_type;
clutter_device_manager_set_pointer_a11y_settings (device->device_manager,
&settings);
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-dwell-click-type-changed",
dwell_click_type);
}
}
static void
emit_dwell_click (ClutterInputDevice *device,
ClutterPointerA11yDwellClickType dwell_click_type)
{
switch (dwell_click_type)
{
case CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY:
emit_button_click (device, CLUTTER_BUTTON_PRIMARY);
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE:
emit_button_click (device, CLUTTER_BUTTON_PRIMARY);
emit_button_click (device, CLUTTER_BUTTON_PRIMARY);
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG:
if (is_dwell_dragging (device))
{
emit_button_release (device, CLUTTER_BUTTON_PRIMARY);
device->ptr_a11y_data->dwell_drag_started = FALSE;
}
else
{
emit_button_press (device, CLUTTER_BUTTON_PRIMARY);
device->ptr_a11y_data->dwell_drag_started = TRUE;
}
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY:
emit_button_click (device, CLUTTER_BUTTON_SECONDARY);
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE:
emit_button_click (device, CLUTTER_BUTTON_MIDDLE);
break;
case CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE:
default:
break;
}
}
static ClutterPointerA11yDwellDirection
get_dwell_direction (ClutterInputDevice *device)
{
float dx, dy;
dx = ABS (device->ptr_a11y_data->dwell_x - device->ptr_a11y_data->current_x);
dy = ABS (device->ptr_a11y_data->dwell_y - device->ptr_a11y_data->current_y);
/* The pointer hasn't moved */
if (!pointer_has_moved (device))
return CLUTTER_A11Y_DWELL_DIRECTION_NONE;
if (device->ptr_a11y_data->dwell_x < device->ptr_a11y_data->current_x)
{
if (dx > dy)
return CLUTTER_A11Y_DWELL_DIRECTION_LEFT;
}
else
{
if (dx > dy)
return CLUTTER_A11Y_DWELL_DIRECTION_RIGHT;
}
if (device->ptr_a11y_data->dwell_y < device->ptr_a11y_data->current_y)
return CLUTTER_A11Y_DWELL_DIRECTION_UP;
return CLUTTER_A11Y_DWELL_DIRECTION_DOWN;
}
static gboolean
trigger_clear_dwell_gesture (gpointer data)
{
ClutterInputDevice *device = data;
device->ptr_a11y_data->dwell_timer = 0;
device->ptr_a11y_data->dwell_gesture_started = FALSE;
return G_SOURCE_REMOVE;
}
static gboolean
trigger_dwell_gesture (gpointer data)
{
ClutterInputDevice *device = data;
ClutterPointerA11yDwellDirection direction;
unsigned int delay = get_dwell_delay (device);
restore_dwell_position (device);
direction = get_dwell_direction (device);
emit_dwell_click (device,
get_dwell_click_type_for_direction (device,
direction));
/* Do not clear the gesture right away, otherwise we'll start another one */
device->ptr_a11y_data->dwell_timer =
clutter_threads_add_timeout (delay, trigger_clear_dwell_gesture, device);
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-stopped",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE);
return G_SOURCE_REMOVE;
}
static void
start_dwell_gesture_timeout (ClutterInputDevice *device)
{
unsigned int delay = get_dwell_delay (device);
device->ptr_a11y_data->dwell_timer =
clutter_threads_add_timeout (delay, trigger_dwell_gesture, device);
device->ptr_a11y_data->dwell_gesture_started = TRUE;
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-started",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE,
delay);
}
static gboolean
trigger_dwell_click (gpointer data)
{
ClutterInputDevice *device = data;
device->ptr_a11y_data->dwell_timer = 0;
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-stopped",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL);
if (get_dwell_mode (device) == CLUTTER_A11Y_DWELL_MODE_GESTURE)
{
if (is_dwell_dragging (device))
emit_dwell_click (device, CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG);
else
start_dwell_gesture_timeout (device);
}
else
{
emit_dwell_click (device, get_dwell_click_type (device));
update_dwell_click_type (device);
}
return G_SOURCE_REMOVE;
}
static void
start_dwell_timeout (ClutterInputDevice *device)
{
unsigned int delay = get_dwell_delay (device);
device->ptr_a11y_data->dwell_timer =
clutter_threads_add_timeout (delay, trigger_dwell_click, device);
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-started",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
delay);
}
static void
stop_dwell_timeout (ClutterInputDevice *device)
{
if (device->ptr_a11y_data->dwell_timer)
{
g_source_remove (device->ptr_a11y_data->dwell_timer);
device->ptr_a11y_data->dwell_timer = 0;
device->ptr_a11y_data->dwell_gesture_started = FALSE;
g_signal_emit_by_name (device->device_manager,
"ptr-a11y-timeout-stopped",
device,
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL);
}
}
static void
update_dwell_position (ClutterInputDevice *device)
{
device->ptr_a11y_data->dwell_x = device->ptr_a11y_data->current_x;
device->ptr_a11y_data->dwell_y = device->ptr_a11y_data->current_y;
}
static void
update_current_position (ClutterInputDevice *device,
float x,
float y)
{
device->ptr_a11y_data->current_x = x;
device->ptr_a11y_data->current_y = y;
}
static gboolean
is_device_core_pointer (ClutterInputDevice *device)
{
ClutterInputDevice *core_pointer;
core_pointer = clutter_device_manager_get_core_device (device->device_manager,
CLUTTER_POINTER_DEVICE);
if (core_pointer == NULL)
return FALSE;
return (core_pointer == device);
}
void
_clutter_input_pointer_a11y_add_device (ClutterInputDevice *device)
{
if (!is_device_core_pointer (device))
return;
device->accessibility_virtual_device =
clutter_device_manager_create_virtual_device (device->device_manager,
CLUTTER_POINTER_DEVICE);
device->ptr_a11y_data = g_new0 (ClutterPtrA11yData, 1);
}
void
_clutter_input_pointer_a11y_remove_device (ClutterInputDevice *device)
{
if (!is_device_core_pointer (device))
return;
/* Terminate a drag if started */
if (is_dwell_dragging (device))
emit_dwell_click (device, CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG);
stop_dwell_timeout (device);
stop_secondary_click_timeout (device);
g_clear_pointer (&device->ptr_a11y_data, g_free);
}
void
_clutter_input_pointer_a11y_on_motion_event (ClutterInputDevice *device,
float x,
float y)
{
if (!is_device_core_pointer (device))
return;
if (!_clutter_is_input_pointer_a11y_enabled (device))
return;
update_current_position (device, x, y);
if (is_secondary_click_enabled (device))
{
if (pointer_has_moved (device))
stop_secondary_click_timeout (device);
}
if (is_dwell_click_enabled (device))
{
if (should_stop_dwell (device))
stop_dwell_timeout (device);
else if (should_start_dwell (device))
start_dwell_timeout (device);
}
if (should_update_dwell_position (device))
update_dwell_position (device);
}
void
_clutter_input_pointer_a11y_on_button_event (ClutterInputDevice *device,
int button,
gboolean pressed)
{
if (!is_device_core_pointer (device))
return;
if (!_clutter_is_input_pointer_a11y_enabled (device))
return;
if (pressed)
{
device->ptr_a11y_data->n_btn_pressed++;
if (is_dwell_click_enabled (device))
stop_dwell_timeout (device);
if (is_dwell_dragging (device))
stop_dwell_timeout (device);
if (is_secondary_click_enabled (device))
{
if (button == CLUTTER_BUTTON_PRIMARY)
{
if (should_start_secondary_click_timeout (device))
start_secondary_click_timeout (device);
}
else if (is_secondary_click_pending (device))
{
stop_secondary_click_timeout (device);
}
}
}
else
{
if (has_button_pressed (device))
device->ptr_a11y_data->n_btn_pressed--;
if (is_secondary_click_triggered (device))
{
emit_button_click (device, CLUTTER_BUTTON_SECONDARY);
stop_secondary_click_timeout (device);
}
if (is_secondary_click_pending (device))
stop_secondary_click_timeout (device);
if (is_dwell_dragging (device))
emit_dwell_click (device, CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG);
}
}
gboolean
_clutter_is_input_pointer_a11y_enabled (ClutterInputDevice *device)
{
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
return (is_secondary_click_enabled (device) || is_dwell_click_enabled (device));
}

View File

@@ -58,6 +58,7 @@
#include "clutter-device-manager-private.h"
#include "clutter-event-private.h"
#include "clutter-feature.h"
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-main.h"
#include "clutter-master-clock.h"
#include "clutter-mutter.h"
@@ -2261,6 +2262,21 @@ _clutter_process_event_details (ClutterActor *stage,
break;
case CLUTTER_MOTION:
#ifdef CLUTTER_WINDOWING_X11
if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
{
if (_clutter_is_input_pointer_a11y_enabled (device))
{
ClutterInputDevice *core_pointer;
gfloat x, y;
clutter_event_get_coords (event, &x, &y);
core_pointer = clutter_device_manager_get_core_device (device->device_manager,
CLUTTER_POINTER_DEVICE);
_clutter_input_pointer_a11y_on_motion_event (core_pointer, x, y);
}
}
#endif /* CLUTTER_WINDOWING_X11 */
/* only the stage gets motion events if they are enabled */
if (!clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage)) &&
event->any.source == NULL)
@@ -2299,6 +2315,22 @@ _clutter_process_event_details (ClutterActor *stage,
/* fallthrough from motion */
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
#ifdef CLUTTER_WINDOWING_X11
if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
{
if (_clutter_is_input_pointer_a11y_enabled (device) && (event->type != CLUTTER_MOTION))
{
ClutterInputDevice *core_pointer;
core_pointer = clutter_device_manager_get_core_device (device->device_manager,
CLUTTER_POINTER_DEVICE);
_clutter_input_pointer_a11y_on_button_event (core_pointer,
event->button.button,
event->type == CLUTTER_BUTTON_PRESS);
}
}
#endif /* CLUTTER_WINDOWING_X11 */
case CLUTTER_SCROLL:
case CLUTTER_TOUCHPAD_PINCH:
case CLUTTER_TOUCHPAD_SWIPE:

View File

@@ -23,6 +23,7 @@ VOID:FLOAT,FLOAT
VOID:INT,INT,INT,INT
VOID:OBJECT
VOID:OBJECT,FLAGS
VOID:OBJECT,FLAGS,UINT
VOID:OBJECT,FLOAT,FLOAT
VOID:OBJECT,FLOAT,FLOAT,FLAGS
VOID:OBJECT,OBJECT

View File

@@ -64,9 +64,6 @@ struct _ClutterMasterClockDefault
/* the current state of the clock, in usecs */
gint64 cur_tick;
/* the previous state of the clock, in usecs, used to compute the delta */
gint64 prev_tick;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 frame_budget;
gint64 remaining_budget;
@@ -77,12 +74,6 @@ struct _ClutterMasterClockDefault
*/
GSource *source;
/* If the master clock is idle that means it has
* fallen back to idle polling for timeline
* progressions and it may have been some time since
* the last real stage update.
*/
guint idle : 1;
guint ensure_next_iteration : 1;
guint paused : 1;
@@ -275,78 +266,12 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
static gint
master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
{
gint64 now, next;
gint swap_delay;
if (!master_clock_is_running (master_clock))
return -1;
/* If all of the stages are busy waiting for a swap-buffers to complete
* then we wait for one to be ready.. */
swap_delay = master_clock_get_swap_wait_time (master_clock);
if (swap_delay != 0)
return swap_delay;
/* When we have sync-to-vblank, we count on swap-buffer requests (or
* swap-buffer-complete events if supported in the backend) to throttle our
* frame rate so no additional delay is needed to start the next frame.
*
* If the master-clock has become idle due to no timeline progression causing
* redraws then we can no longer rely on vblank synchronization because the
* last real stage update/redraw may have happened a long time ago and so we
* fallback to polling for timeline progressions every 1/frame_rate seconds.
*
* (NB: if there aren't even any timelines running then the master clock will
* be completely stopped in master_clock_is_running())
*/
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_THROTTLE) &&
!master_clock->idle)
{
CLUTTER_NOTE (SCHEDULER, "swap throttling available and updated stages");
return 0;
}
if (master_clock->prev_tick == 0)
{
/* If we weren't previously running, then draw the next frame
* immediately
*/
CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately");
return 0;
}
/* Otherwise, wait at least 1/frame_rate seconds since we last
* started a frame
*/
now = g_source_get_time (master_clock->source);
next = master_clock->prev_tick;
/* If time has gone backwards then there's no way of knowing how
long we should wait so let's just dispatch immediately */
if (now <= next)
{
CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
return 0;
}
next += (1000000L / clutter_get_default_frame_rate ());
if (next <= now)
{
CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
1000000L / (gulong) clutter_get_default_frame_rate ());
return 0;
}
else
{
CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
(next - now) / 1000);
return (next - now) / 1000;
}
return master_clock_get_swap_wait_time (master_clock);
}
static void
@@ -530,7 +455,6 @@ clutter_clock_dispatch (GSource *source,
{
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
gboolean stages_updated = FALSE;
GSList *stages;
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
@@ -550,8 +474,6 @@ clutter_clock_dispatch (GSource *source,
*/
stages = master_clock_list_ready_stages (master_clock);
master_clock->idle = FALSE;
/* Each frame is split into three separate phases: */
/* 1. process all the events; each stage goes through its events queue
@@ -564,19 +486,12 @@ clutter_clock_dispatch (GSource *source,
master_clock_advance_timelines (master_clock);
/* 3. relayout and redraw the stages */
stages_updated = master_clock_update_stages (master_clock, stages);
/* The master clock goes idle if no stages were updated and falls back
* to polling for timeline progressions... */
if (!stages_updated)
master_clock->idle = TRUE;
master_clock_update_stages (master_clock, stages);
master_clock_reschedule_stage_updates (master_clock, stages);
g_slist_free_full (stages, g_object_unref);
master_clock->prev_tick = master_clock->cur_tick;
_clutter_threads_release_lock ();
return TRUE;
@@ -608,7 +523,6 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
source = clutter_clock_source_new (self);
self->source = source;
self->idle = FALSE;
self->ensure_next_iteration = FALSE;
self->paused = FALSE;

View File

@@ -43,6 +43,11 @@ void clutter_stage_capture_into (ClutterStage *stage,
cairo_rectangle_int_t *rect,
uint8_t *data);
CLUTTER_EXPORT
ClutterStageView * clutter_stage_get_view_at (ClutterStage *stage,
float x,
float y);
CLUTTER_EXPORT
void clutter_stage_freeze_updates (ClutterStage *stage);

View File

@@ -75,6 +75,7 @@
#include "clutter-private.h"
#include "cogl/cogl.h"
#include "cogl/cogl-trace.h"
/* <private>
* ClutterStageHint:
@@ -688,6 +689,8 @@ _clutter_stage_paint_view (ClutterStage *stage,
if (!priv->impl)
return;
COGL_TRACE_BEGIN_SCOPED (ClutterStagePaintView, "Paint (view)");
clutter_stage_do_paint_view (stage, view, clip);
g_signal_emit (stage, stage_signals[AFTER_PAINT], 0);
}
@@ -1225,22 +1228,31 @@ _clutter_stage_do_update (ClutterStage *stage)
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
return FALSE;
COGL_TRACE_BEGIN_SCOPED (ClutterStageDoUpdate, "Update");
/* NB: We need to ensure we have an up to date layout *before* we
* check or clear the pending redraws flag since a relayout may
* queue a redraw.
*/
COGL_TRACE_BEGIN (ClutterStageRelayout, "Layout");
_clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
COGL_TRACE_END (ClutterStageRelayout);
if (!priv->redraw_pending)
return FALSE;
if (stage_was_relayout)
pointers = _clutter_stage_check_updated_pointers (stage);
clutter_stage_maybe_finish_queue_redraws (stage);
COGL_TRACE_BEGIN (ClutterStagePaint, "Paint");
clutter_stage_maybe_finish_queue_redraws (stage);
clutter_stage_do_redraw (stage);
COGL_TRACE_END (ClutterStagePaint);
/* reset the guard, so that new redraws are possible */
priv->redraw_pending = FALSE;
@@ -1254,12 +1266,16 @@ _clutter_stage_do_update (ClutterStage *stage)
}
#endif /* CLUTTER_ENABLE_DEBUG */
COGL_TRACE_BEGIN (ClutterStagePick, "Pick");
while (pointers)
{
_clutter_input_device_update (pointers->data, NULL, TRUE);
pointers = g_slist_delete_link (pointers, pointers);
}
COGL_TRACE_END (ClutterStagePick);
return TRUE;
}
@@ -1570,10 +1586,13 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
return retval;
}
static ClutterStageView *
get_view_at (ClutterStage *stage,
int x,
int y)
/**
* clutter_stage_get_view_at: (skip)
*/
ClutterStageView *
clutter_stage_get_view_at (ClutterStage *stage,
float x,
float y)
{
ClutterStagePrivate *priv = stage->priv;
GList *l;
@@ -1620,7 +1639,7 @@ _clutter_stage_do_pick (ClutterStage *stage,
if (x < 0 || x >= stage_width || y < 0 || y >= stage_height)
return actor;
view = get_view_at (stage, x, y);
view = clutter_stage_get_view_at (stage, x, y);
if (view)
return _clutter_stage_do_pick_on_view (stage, x, y, mode, view);
@@ -2945,6 +2964,8 @@ clutter_stage_read_pixels (ClutterStage *stage,
float pixel_height;
uint8_t *pixels;
COGL_TRACE_BEGIN_SCOPED (ClutterStageReadPixels, "Read Pixels");
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
priv = stage->priv;
@@ -3010,7 +3031,11 @@ clutter_stage_read_pixels (ClutterStage *stage,
* @y: Y coordinate to check
*
* Checks the scene at the coordinates @x and @y and returns a pointer
* to the #ClutterActor at those coordinates.
* to the #ClutterActor at those coordinates. The result is the actor which
* would be at the specified location on the next redraw, and is not
* necessarily that which was there on the previous redraw. This allows the
* function to perform chronologically correctly after any queued changes to
* the scene, and even if nothing has been drawn.
*
* By using @pick_mode it is possible to control which actors will be
* painted and thus available.

View File

@@ -46,6 +46,8 @@
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "cogl/cogl-trace.h"
typedef struct _ClutterStageViewCoglPrivate
{
/*
@@ -183,38 +185,56 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
return;
}
/* We only extrapolate presentation times for 150ms - this is somewhat
* arbitrary. The reasons it might not be accurate for larger times are
* that the refresh interval might be wrong or the vertical refresh
* might be downclocked if nothing is going on onscreen.
*/
if (stage_cogl->last_presentation_time == 0||
stage_cogl->last_presentation_time < now - 150000)
refresh_rate = stage_cogl->refresh_rate;
if (refresh_rate <= 0.0)
refresh_rate = clutter_get_default_frame_rate ();
refresh_interval = (gint64) (0.5 + G_USEC_PER_SEC / refresh_rate);
if (refresh_interval == 0)
{
stage_cogl->update_time = now;
return;
}
refresh_rate = stage_cogl->refresh_rate;
if (refresh_rate == 0.0)
refresh_rate = 60.0;
refresh_interval = (gint64) (0.5 + 1000000 / refresh_rate);
if (refresh_interval == 0)
refresh_interval = 16667; /* 1/60th second */
min_render_time_allowed = refresh_interval / 2;
max_render_time_allowed = refresh_interval - 1000 * sync_delay;
/* Be robust in the case of incredibly bogus refresh rate */
if (max_render_time_allowed <= 0)
{
g_warning ("Unsupported monitor refresh rate detected. "
"(Refresh rate: %.3f, refresh interval: %ld)",
refresh_rate,
refresh_interval);
stage_cogl->update_time = now;
return;
}
if (min_render_time_allowed > max_render_time_allowed)
min_render_time_allowed = max_render_time_allowed;
next_presentation_time = stage_cogl->last_presentation_time + refresh_interval;
/* Get next_presentation_time closer to its final value, to reduce
* the number of while iterations below.
*/
if (next_presentation_time < now)
{
int64_t last_virtual_presentation_time = now - now % refresh_interval;
int64_t hardware_clock_phase =
stage_cogl->last_presentation_time % refresh_interval;
next_presentation_time =
last_virtual_presentation_time + hardware_clock_phase;
}
while (next_presentation_time < now + min_render_time_allowed)
next_presentation_time += refresh_interval;
stage_cogl->update_time = next_presentation_time - max_render_time_allowed;
if (stage_cogl->update_time == stage_cogl->last_update_time)
stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval;
}
static gint64
@@ -233,6 +253,7 @@ clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
stage_cogl->last_update_time = stage_cogl->update_time;
stage_cogl->update_time = -1;
}
@@ -905,26 +926,16 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
*/
if (use_clipped_redraw)
{
if (use_clipped_redraw && clip_region_empty)
if (clip_region_empty)
{
do_swap_buffer = FALSE;
}
else if (use_clipped_redraw)
else
{
swap_region = fb_clip_region;
g_assert (swap_region.width > 0);
do_swap_buffer = TRUE;
}
else
{
swap_region = (cairo_rectangle_int_t) {
.x = 0,
.y = 0,
.width = view_rect.width * fb_scale,
.height = view_rect.height * fb_scale,
};
do_swap_buffer = TRUE;
}
}
else
{
@@ -934,6 +945,9 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
if (do_swap_buffer)
{
COGL_TRACE_BEGIN_SCOPED (ClutterStageCoglRedrawViewSwapFramebuffer,
"Paint (swap framebuffer)");
if (clutter_stage_view_get_onscreen (view) !=
clutter_stage_view_get_framebuffer (view))
{
@@ -958,6 +972,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
gboolean swap_event = FALSE;
GList *l;
COGL_TRACE_BEGIN (ClutterStageCoglRedraw, "Paint (Cogl Redraw)");
for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next)
{
ClutterStageView *view = l->data;
@@ -981,6 +997,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
stage_cogl->initialized_redraw_clip = FALSE;
stage_cogl->frame_count++;
COGL_TRACE_END (ClutterStageCoglRedraw);
}
static void

View File

@@ -53,6 +53,7 @@ struct _ClutterStageCogl
gint64 last_presentation_time;
gint64 update_time;
int64_t last_update_time;
/* We only enable clipped redraws after 2 frames, since we've seen
* a lot of drivers can struggle to get going and may output some

View File

@@ -739,31 +739,33 @@ get_button_index (gint button)
}
static void
emulate_button_press (ClutterInputDeviceEvdev *device)
emulate_button_press (ClutterInputDeviceEvdev *device_evdev)
{
gint btn = device->mousekeys_btn;
ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev);
gint btn = device_evdev->mousekeys_btn;
if (device->mousekeys_btn_states[get_button_index (btn)])
if (device_evdev->mousekeys_btn_states[get_button_index (btn)])
return;
clutter_virtual_input_device_notify_button (device->mousekeys_virtual_device,
clutter_virtual_input_device_notify_button (device->accessibility_virtual_device,
g_get_monotonic_time (), btn,
CLUTTER_BUTTON_STATE_PRESSED);
device->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_PRESSED;
device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_PRESSED;
}
static void
emulate_button_release (ClutterInputDeviceEvdev *device)
emulate_button_release (ClutterInputDeviceEvdev *device_evdev)
{
gint btn = device->mousekeys_btn;
ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev);
gint btn = device_evdev->mousekeys_btn;
if (device->mousekeys_btn_states[get_button_index (btn)] == CLUTTER_BUTTON_STATE_RELEASED)
if (device_evdev->mousekeys_btn_states[get_button_index (btn)] == CLUTTER_BUTTON_STATE_RELEASED)
return;
clutter_virtual_input_device_notify_button (device->mousekeys_virtual_device,
clutter_virtual_input_device_notify_button (device->accessibility_virtual_device,
g_get_monotonic_time (), btn,
CLUTTER_BUTTON_STATE_RELEASED);
device->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_RELEASED;
device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_RELEASED;
}
static void
@@ -830,17 +832,18 @@ mousekeys_get_speed_factor (ClutterInputDeviceEvdev *device,
#undef MOUSEKEYS_CURVE
static void
emulate_pointer_motion (ClutterInputDeviceEvdev *device,
emulate_pointer_motion (ClutterInputDeviceEvdev *device_evdev,
gint dx,
gint dy)
{
ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev);
gdouble dx_motion;
gdouble dy_motion;
gdouble speed;
gint64 time_us;
time_us = g_get_monotonic_time ();
speed = mousekeys_get_speed_factor (device, time_us);
speed = mousekeys_get_speed_factor (device_evdev, time_us);
if (dx < 0)
dx_motion = floor (((gdouble) dx) * speed);
@@ -852,7 +855,7 @@ emulate_pointer_motion (ClutterInputDeviceEvdev *device,
else
dy_motion = ceil (((gdouble) dy) * speed);
clutter_virtual_input_device_notify_relative_motion (device->mousekeys_virtual_device,
clutter_virtual_input_device_notify_relative_motion (device->accessibility_virtual_device,
time_us, dx_motion, dy_motion);
}
static gboolean
@@ -865,51 +868,53 @@ is_numlock_active (ClutterInputDeviceEvdev *device)
}
static void
enable_mousekeys (ClutterInputDeviceEvdev *device)
enable_mousekeys (ClutterInputDeviceEvdev *device_evdev)
{
ClutterDeviceManager *manager;
ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev);
ClutterDeviceManager *manager = device->device_manager;
device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY;
device->move_mousekeys_timer = 0;
device->mousekeys_first_motion_time = 0;
device->mousekeys_last_motion_time = 0;
device->last_mousekeys_key = 0;
device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY;
device_evdev->move_mousekeys_timer = 0;
device_evdev->mousekeys_first_motion_time = 0;
device_evdev->mousekeys_last_motion_time = 0;
device_evdev->last_mousekeys_key = 0;
if (device->mousekeys_virtual_device)
if (device->accessibility_virtual_device)
return;
manager = CLUTTER_INPUT_DEVICE (device)->device_manager;
device->mousekeys_virtual_device =
device->accessibility_virtual_device =
clutter_device_manager_create_virtual_device (manager,
CLUTTER_POINTER_DEVICE);
}
static void
disable_mousekeys (ClutterInputDeviceEvdev *device)
disable_mousekeys (ClutterInputDeviceEvdev *device_evdev)
{
stop_mousekeys_move (device);
ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev);
stop_mousekeys_move (device_evdev);
/* Make sure we don't leave button pressed behind... */
if (device->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_PRIMARY)])
if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_PRIMARY)])
{
device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY;
emulate_button_release (device);
device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY;
emulate_button_release (device_evdev);
}
if (device->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_MIDDLE)])
if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_MIDDLE)])
{
device->mousekeys_btn = CLUTTER_BUTTON_MIDDLE;
emulate_button_release (device);
device_evdev->mousekeys_btn = CLUTTER_BUTTON_MIDDLE;
emulate_button_release (device_evdev);
}
if (device->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_SECONDARY)])
if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_SECONDARY)])
{
device->mousekeys_btn = CLUTTER_BUTTON_SECONDARY;
emulate_button_release (device);
device_evdev->mousekeys_btn = CLUTTER_BUTTON_SECONDARY;
emulate_button_release (device_evdev);
}
if (device->mousekeys_virtual_device)
g_clear_object (&device->mousekeys_virtual_device);
if (device->accessibility_virtual_device)
g_clear_object (&device->accessibility_virtual_device);
}
static gboolean

View File

@@ -94,7 +94,6 @@ struct _ClutterInputDeviceEvdev
gdouble mousekeys_curve_factor;
guint move_mousekeys_timer;
guint16 last_mousekeys_key;
ClutterVirtualInputDevice *mousekeys_virtual_device;
};
GType _clutter_input_device_evdev_get_type (void) G_GNUC_CONST;

View File

@@ -133,6 +133,7 @@ clutter_sources = [
'clutter-input-device-tool.c',
'clutter-input-focus.c',
'clutter-input-method.c',
'clutter-input-pointer-a11y.c',
'clutter-virtual-input-device.c',
'clutter-interval.c',
'clutter-keyframe-transition.c',
@@ -195,6 +196,7 @@ clutter_private_headers = [
'clutter-id-pool.h',
'clutter-input-focus-private.h',
'clutter-input-method-private.h',
'clutter-input-pointer-a11y-private.h',
'clutter-master-clock.h',
'clutter-master-clock-default.h',
'clutter-offscreen-effect-private.h',
@@ -504,7 +506,12 @@ libmutter_clutter_dep = declare_dependency(
)
if have_introspection
clutter_introspection_args = introspection_args + clutter_c_args
clutter_introspection_args = introspection_args + [
'-DCLUTTER_SYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)),
'-DCLUTTER_COMPILATION=1',
'-DCOGL_DISABLE_DEPRECATION_WARNINGS',
'-DG_LOG_DOMAIN="Clutter"'
]
libmutter_clutter_gir = gnome.generate_gir(libmutter_clutter,
sources: [

View File

@@ -30,6 +30,7 @@
#include "clutter-backend-x11.h"
#include "clutter-input-device-xi2.h"
#include "clutter-input-device-tool-xi2.h"
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-virtual-input-device-x11.h"
#include "clutter-stage-x11.h"
@@ -1273,6 +1274,60 @@ translate_pad_event (ClutterEvent *event,
return TRUE;
}
static void
handle_raw_event (ClutterDeviceManagerXI2 *manager_xi2,
XEvent *xevent)
{
ClutterInputDevice *device;
XGenericEventCookie *cookie;
XIEvent *xi_event;
XIRawEvent *xev;
float x,y;
cookie = &xevent->xcookie;
xi_event = (XIEvent *) cookie->data;
xev = (XIRawEvent *) xi_event;
device = g_hash_table_lookup (manager_xi2->devices_by_id,
GINT_TO_POINTER (xev->deviceid));
if (device == NULL)
return;
if (!_clutter_is_input_pointer_a11y_enabled (device))
return;
switch (cookie->evtype)
{
case XI_RawMotion:
CLUTTER_NOTE (EVENT,
"raw motion: device:%d '%s'",
device->id,
device->device_name);
/* We don't get actual pointer location with raw events, and we cannot
* rely on `clutter_input_device_get_coords()` either because of
* unreparented toplevels (like all client-side decoration windows),
* so we need to explicitely query the pointer here...
*/
if (clutter_input_device_xi2_get_pointer_location (device, &x, &y))
_clutter_input_pointer_a11y_on_motion_event (device, x, y);
break;
case XI_RawButtonPress:
case XI_RawButtonRelease:
CLUTTER_NOTE (EVENT,
"raw button %s: device:%d '%s' button %i",
cookie->evtype == XI_RawButtonPress
? "press "
: "release",
device->id,
device->device_name,
xev->detail);
_clutter_input_pointer_a11y_on_button_event (device,
xev->detail,
(cookie->evtype == XI_RawButtonPress));
break;
}
}
static ClutterTranslateReturn
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
gpointer native,
@@ -1303,6 +1358,14 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
if (!xi_event)
return CLUTTER_TRANSLATE_REMOVE;
if (cookie->evtype == XI_RawMotion ||
cookie->evtype == XI_RawButtonPress ||
cookie->evtype == XI_RawButtonRelease)
{
handle_raw_event (manager_xi2, xevent);
return CLUTTER_TRANSLATE_REMOVE;
}
if (!(xi_event->evtype == XI_HierarchyChanged ||
xi_event->evtype == XI_DeviceChanged ||
xi_event->evtype == XI_PropertyEvent))
@@ -2031,7 +2094,7 @@ clutter_device_manager_xi2_constructed (GObject *gobject)
GHashTable *masters, *slaves;
XIDeviceInfo *info;
XIEventMask event_mask;
unsigned char mask[2] = { 0, };
unsigned char mask[(XI_LASTEVENT + 7) / 8] = { 0, };
int n_devices, i;
backend_x11 =
@@ -2083,6 +2146,19 @@ clutter_device_manager_xi2_constructed (GObject *gobject)
event_mask.mask_len = sizeof (mask);
event_mask.mask = mask;
clutter_device_manager_xi2_select_events (manager,
clutter_x11_get_root_window (),
&event_mask);
memset(mask, 0, sizeof (mask));
XISetMask (mask, XI_RawMotion);
XISetMask (mask, XI_RawButtonPress);
XISetMask (mask, XI_RawButtonRelease);
event_mask.deviceid = XIAllMasterDevices;
event_mask.mask_len = sizeof (mask);
event_mask.mask = mask;
clutter_device_manager_xi2_select_events (manager,
clutter_x11_get_root_window (),
&event_mask);

View File

@@ -46,6 +46,11 @@ struct _ClutterInputDeviceXI2
gint device_id;
ClutterInputDeviceTool *current_tool;
guint inhibit_pointer_query_timer;
gboolean query_status;
float current_x;
float current_y;
#ifdef HAVE_LIBWACOM
WacomDevice *wacom_device;
GArray *group_modes;
@@ -112,6 +117,9 @@ clutter_input_device_xi2_finalize (GObject *object)
if (device_xi2->group_modes)
g_array_unref (device_xi2->group_modes);
if (device_xi2->inhibit_pointer_query_timer)
g_source_remove (device_xi2->inhibit_pointer_query_timer);
#endif
G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object);
@@ -293,6 +301,75 @@ clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device)
return device_xi2->current_tool;
}
static gboolean
clutter_input_device_xi2_query_pointer_location (ClutterInputDeviceXI2 *device_xi2)
{
Window xroot_window, xchild_window;
double xroot_x, xroot_y, xwin_x, xwin_y;
XIButtonState button_state;
XIModifierState mod_state;
XIGroupState group_state;
int result;
clutter_x11_trap_x_errors ();
result = XIQueryPointer (clutter_x11_get_default_display (),
device_xi2->device_id,
clutter_x11_get_root_window (),
&xroot_window,
&xchild_window,
&xroot_x, &xroot_y,
&xwin_x, &xwin_y,
&button_state,
&mod_state,
&group_state);
clutter_x11_untrap_x_errors ();
if (!result)
return FALSE;
device_xi2->current_x = (float) xroot_x;
device_xi2->current_y = (float) xroot_y;
return TRUE;
}
static gboolean
clear_inhibit_pointer_query_cb (gpointer data)
{
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (data);
device_xi2->inhibit_pointer_query_timer = 0;
return G_SOURCE_REMOVE;
}
gboolean
clutter_input_device_xi2_get_pointer_location (ClutterInputDevice *device,
float *x,
float *y)
{
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device);
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_XI2 (device_xi2), FALSE);
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, FALSE);
/* Throttle XServer queries and roundtrips using an idle timeout */
if (device_xi2->inhibit_pointer_query_timer == 0)
{
device_xi2->query_status =
clutter_input_device_xi2_query_pointer_location (device_xi2);
device_xi2->inhibit_pointer_query_timer =
clutter_threads_add_idle (clear_inhibit_pointer_query_cb, device_xi2);
}
*x = device_xi2->current_x;
*y = device_xi2->current_y;
return device_xi2->query_status;
}
#ifdef HAVE_LIBWACOM
void
clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device,

View File

@@ -48,6 +48,9 @@ void _clutter_input_device_xi2_translate_state (ClutterEvent *event,
void clutter_input_device_xi2_update_tool (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device);
gboolean clutter_input_device_xi2_get_pointer_location (ClutterInputDevice *device,
float *x,
float *y);
#ifdef HAVE_LIBWACOM
void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device,

View File

@@ -12,19 +12,19 @@ clutter_c_args = [
]
clutter_debug_c_args = []
if buildtype.startswith('debug')
clutter_debug_c_args += '-DG_DISABLE_CAST_CHECKS'
if buildtype == 'debug'
clutter_debug_c_args += '-DCLUTTER_ENABLE_DEBUG'
endif
elif buildtype == 'release'
if get_option('debug')
clutter_debug_c_args += [
'-DCLUTTER_ENABLE_DEBUG',
'-fno-omit-frame-pointer'
]
elif buildtype != 'plain'
clutter_debug_c_args += [
'-DG_DISABLE_ASSERT',
'-DG_DISABLE_CHECKS',
'-DG_DISABLE_CAST_CHECKS',
]
endif
supported_clutter_debug_c_args = cc.get_supported_arguments(clutter_debug_c_args)
clutter_c_args += clutter_debug_c_args
clutter_pkg_deps = [

View File

@@ -4,6 +4,9 @@
/* Have GLES 2.0 for rendering */
#mesondefine HAVE_COGL_GLES2
/* Building with Sysprof profiling suport */
#mesondefine HAVE_TRACING
/* Enable unit tests */
#mesondefine ENABLE_UNIT_TESTS

View File

@@ -29,7 +29,6 @@
*/
#include "cogl-config.h"
#include "cogl-defines.h"
#include <string.h>
#include <math.h>
@@ -309,66 +308,3 @@ cogl_pixel_format_to_string (CoglPixelFormat format)
g_assert_not_reached ();
}
#ifdef COGL_HAS_LIBDRM
typedef struct _PixelFormatMap {
uint32_t drm_format;
CoglPixelFormat cogl_format;
CoglTextureComponents cogl_components;
} PixelFormatMap;
static const PixelFormatMap pixel_format_map[] = {
/* DRM formats are defined as little-endian, not machine endian. */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
{ DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#elif G_BYTE_ORDER == G_BIG_ENDIAN
/* DRM_FORMAT_RGB565 cannot be expressed. */
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#else
#error "unexpected G_BYTE_ORDER"
#endif
};
gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components)
{
const size_t n = G_N_ELEMENTS (pixel_format_map);
size_t i;
for (i = 0; i < n; i++)
{
if (pixel_format_map[i].drm_format == drm_format)
break;
}
if (i == n)
return FALSE;
if (out_format)
*out_format = pixel_format_map[i].cogl_format;
if (out_components)
*out_components = pixel_format_map[i].cogl_components;
return TRUE;
}
#endif

View File

@@ -38,10 +38,6 @@
#include <stdint.h>
#include <stddef.h>
#ifdef COGL_HAS_LIBDRM
#include <drm_fourcc.h>
#endif
#include <cogl/cogl-defines.h>
#include <glib.h>
@@ -62,9 +58,6 @@ G_BEGIN_DECLS
*
* Other examples of factors that can influence the layout in memory are the
* system's endianness.
*
* This file also contains methods to map Linux DRM 4CC codes to
* CoglPixelFormats.
*/
#define COGL_A_BIT (1 << 4)
@@ -302,34 +295,6 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
const char *
cogl_pixel_format_to_string (CoglPixelFormat format);
#ifdef COGL_HAS_LIBDRM
/* added in libdrm 2.4.95 */
#ifndef DRM_FORMAT_INVALID
#define DRM_FORMAT_INVALID 0
#endif
/**
* cogl_pixel_format_from_drm_format:
* @drm_format: The DRM 4CC code (as specified in drm_fourcc.h)
* @out_format: (optional): The corresponding #CoglPixelFormat (if successful)
* @out_components: (optional): The corresponding #CoglTextureComponents (if
* sucessful)
*
* Does an internal lookup to find a #CoglPixelFormat that matches the given
* DRM 4CC code. If no such format could be found, this function will return
* %FALSE and the output parameters will stay untouched.
*
* Returns: %TRUE if a #CoglPixelFormat corresponding to the 4CC code exists,
* %FALSE otherwise.
*/
gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components);
#endif
G_END_DECLS
#endif /* __COGL_PIXEL_FORMAT_H__ */

258
cogl/cogl/cogl-trace.c Normal file
View File

@@ -0,0 +1,258 @@
/*
* Copyright 2018 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include "cogl-config.h"
#ifdef HAVE_TRACING
#include "cogl/cogl-trace.h"
#include <sysprof-capture.h>
#include <syscall.h>
#include <sys/types.h>
#include <unistd.h>
#define COGL_TRACE_OUTPUT_FILE "cogl-trace-sp-capture.syscap"
#define BUFFER_LENGTH (4096 * 4)
typedef struct
{
int fd;
char *filename;
char *group;
} TraceData;
static void
trace_data_free (gpointer user_data)
{
TraceData *data = user_data;
data->fd = -1;
g_clear_pointer (&data->group, g_free);
g_clear_pointer (&data->filename, g_free);
g_free (data);
}
static void cogl_trace_thread_context_free (gpointer data);
GPrivate cogl_trace_thread_data = G_PRIVATE_INIT (cogl_trace_thread_context_free);
CoglTraceContext *cogl_trace_context;
GMutex cogl_trace_mutex;
static CoglTraceContext *
cogl_trace_context_new (int fd,
const char *filename)
{
CoglTraceContext *context;
SysprofCaptureWriter *writer;
if (fd != -1)
{
g_debug ("Initializing trace context with fd=%d", fd);
writer = sysprof_capture_writer_new_from_fd (fd, BUFFER_LENGTH);
}
else if (filename != NULL)
{
g_debug ("Initializing trace context with filename='%s'", filename);
writer = sysprof_capture_writer_new (filename, BUFFER_LENGTH);
}
else
{
g_debug ("Initializing trace context with default filename");
writer = sysprof_capture_writer_new (COGL_TRACE_OUTPUT_FILE, BUFFER_LENGTH);
}
context = g_new0 (CoglTraceContext, 1);
context->writer = writer;
return context;
}
static void
cogl_trace_context_free (CoglTraceContext *trace_context)
{
g_clear_pointer (&trace_context->writer, sysprof_capture_writer_unref);
g_free (trace_context);
}
static void
ensure_trace_context (TraceData *data)
{
g_mutex_lock (&cogl_trace_mutex);
if (!cogl_trace_context)
cogl_trace_context = cogl_trace_context_new (data->fd, data->filename);
g_mutex_unlock (&cogl_trace_mutex);
}
static CoglTraceThreadContext *
cogl_trace_thread_context_new (const char *group)
{
CoglTraceThreadContext *thread_context;
pid_t tid;
tid = (pid_t) syscall (SYS_gettid);
thread_context = g_new0 (CoglTraceThreadContext, 1);
thread_context->cpu_id = -1;
thread_context->pid = getpid ();
thread_context->group =
group ? g_strdup (group) : g_strdup_printf ("t:%d", tid);
return thread_context;
}
static gboolean
enable_tracing_idle_callback (gpointer user_data)
{
CoglTraceThreadContext *thread_context =
g_private_get (&cogl_trace_thread_data);
TraceData *data = user_data;
ensure_trace_context (data);
if (thread_context)
{
g_warning ("Tracing already enabled");
return G_SOURCE_REMOVE;
}
thread_context = cogl_trace_thread_context_new (data->group);
g_private_set (&cogl_trace_thread_data, thread_context);
return G_SOURCE_REMOVE;
}
static void
cogl_trace_thread_context_free (gpointer data)
{
CoglTraceThreadContext *thread_context = data;
if (!thread_context)
return;
g_free (thread_context->group);
g_free (thread_context);
}
static gboolean
disable_tracing_idle_callback (gpointer user_data)
{
CoglTraceThreadContext *thread_context =
g_private_get (&cogl_trace_thread_data);
CoglTraceContext *trace_context;
if (!thread_context)
{
g_warning ("Tracing not enabled");
return G_SOURCE_REMOVE;
}
g_private_replace (&cogl_trace_thread_data, NULL);
g_mutex_lock (&cogl_trace_mutex);
trace_context = cogl_trace_context;
sysprof_capture_writer_flush (trace_context->writer);
g_clear_pointer (&cogl_trace_context, cogl_trace_context_free);
g_mutex_unlock (&cogl_trace_mutex);
return G_SOURCE_REMOVE;
}
static void
set_tracing_enabled_on_thread (GMainContext *main_context,
const char *group,
int fd,
const char *filename)
{
TraceData *data;
GSource *source;
data = g_new0 (TraceData, 1);
data->fd = fd;
data->group = group ? strdup (group) : NULL;
data->filename = filename ? strdup (filename) : NULL;
source = g_idle_source_new ();
g_source_set_callback (source,
enable_tracing_idle_callback,
data,
trace_data_free);
g_source_attach (source, main_context);
g_source_unref (source);
}
void
cogl_set_tracing_enabled_on_thread_with_fd (GMainContext *main_context,
const char *group,
int fd)
{
set_tracing_enabled_on_thread (main_context, group, fd, NULL);
}
void
cogl_set_tracing_enabled_on_thread (GMainContext *main_context,
const char *group,
const char *filename)
{
set_tracing_enabled_on_thread (main_context, group, -1, filename);
}
void
cogl_set_tracing_disabled_on_thread (GMainContext *main_context)
{
GSource *source;
source = g_idle_source_new ();
g_source_set_callback (source, disable_tracing_idle_callback, NULL, NULL);
g_source_attach (source, main_context);
g_source_unref (source);
}
#else
#include <string.h>
#include <stdio.h>
void
cogl_set_tracing_enabled_on_thread_with_fd (void *data,
const char *group,
int fd)
{
fprintf (stderr, "Tracing not enabled");
}
void
cogl_set_tracing_enabled_on_thread (void *data,
const char *group,
const char *filename)
{
fprintf (stderr, "Tracing not enabled");
}
void
cogl_set_tracing_disabled_on_thread (void *data)
{
fprintf (stderr, "Tracing not enabled");
}
#endif /* HAVE_TRACING */

147
cogl/cogl/cogl-trace.h Normal file
View File

@@ -0,0 +1,147 @@
/*
* Copyright 2018 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef COGL_TRACE_H
#define COGL_TRACE_H
#include "cogl-config.h"
#ifdef HAVE_TRACING
#include <glib.h>
#include <sysprof-capture-writer.h>
#include <sysprof-clock.h>
#include <stdint.h>
#include <errno.h>
typedef struct _CoglTraceContext
{
SysprofCaptureWriter *writer;
} CoglTraceContext;
typedef struct _CoglTraceThreadContext
{
int cpu_id;
GPid pid;
char *group;
} CoglTraceThreadContext;
typedef struct _CoglTraceHead
{
SysprofTimeStamp begin_time;
const char *name;
} CoglTraceHead;
extern GPrivate cogl_trace_thread_data;
extern CoglTraceContext *cogl_trace_context;
extern GMutex cogl_trace_mutex;
void cogl_set_tracing_enabled_on_thread_with_fd (GMainContext *main_context,
const char *group,
int fd);
void cogl_set_tracing_enabled_on_thread (GMainContext *main_context,
const char *group,
const char *filename);
void cogl_set_tracing_disabled_on_thread (GMainContext *main_context);
static inline void
cogl_trace_begin (CoglTraceHead *head,
const char *name)
{
head->begin_time = g_get_monotonic_time () * 1000;
head->name = name;
}
static inline void
cogl_trace_end (CoglTraceHead *head)
{
SysprofTimeStamp end_time;
CoglTraceContext *trace_context;
CoglTraceThreadContext *trace_thread_context;
end_time = g_get_monotonic_time () * 1000;
trace_context = cogl_trace_context;
trace_thread_context = g_private_get (&cogl_trace_thread_data);
g_mutex_lock (&cogl_trace_mutex);
if (!sysprof_capture_writer_add_mark (trace_context->writer,
head->begin_time,
trace_thread_context->cpu_id,
trace_thread_context->pid,
(uint64_t) end_time - head->begin_time,
trace_thread_context->group,
head->name,
NULL))
{
/* XXX: g_main_context_get_thread_default() might be wrong, it probably
* needs to store the GMainContext in CoglTraceThreadContext when creating
* and use it here.
*/
if (errno == EPIPE)
cogl_set_tracing_disabled_on_thread (g_main_context_get_thread_default ());
}
g_mutex_unlock (&cogl_trace_mutex);
}
static inline void
cogl_auto_trace_end_helper (CoglTraceHead **head)
{
if (*head)
cogl_trace_end (*head);
}
#define COGL_TRACE_BEGIN(Name, description) \
CoglTraceHead CoglTrace##Name = { 0 }; \
if (g_private_get (&cogl_trace_thread_data)) \
cogl_trace_begin (&CoglTrace##Name, description); \
#define COGL_TRACE_END(Name)\
if (g_private_get (&cogl_trace_thread_data)) \
cogl_trace_end (&CoglTrace##Name);
#define COGL_TRACE_BEGIN_SCOPED(Name, description) \
CoglTraceHead CoglTrace##Name = { 0 }; \
__attribute__((cleanup (cogl_auto_trace_end_helper))) \
CoglTraceHead *ScopedCoglTrace##Name = NULL; \
if (g_private_get (&cogl_trace_thread_data)) \
{ \
cogl_trace_begin (&CoglTrace##Name, description); \
ScopedCoglTrace##Name = &CoglTrace##Name; \
}
#else /* HAVE_TRACING */
#include <stdio.h>
#define COGL_TRACE_BEGIN(Name, description) (void) 0
#define COGL_TRACE_END(Name) (void) 0
#define COGL_TRACE_BEGIN_SCOPED(Name, description) (void) 0
void cogl_set_tracing_enabled_on_thread_with_fd (void *data,
const char *group,
int fd);
void cogl_set_tracing_enabled_on_thread (void *data,
const char *group,
const char *filename);
void cogl_set_tracing_disabled_on_thread (void *data);
#endif /* HAVE_TRACING */
#endif /* COGL_TRACE_H */

View File

@@ -111,20 +111,8 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
switch (format)
{
case COGL_PIXEL_FORMAT_A_8:
/* If the driver doesn't natively support alpha textures then we
* will use a red component texture with a swizzle to implement
* the texture */
if (_cogl_has_private_feature
(context, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) == 0)
{
glintformat = GL_RED;
glformat = GL_RED;
}
else
{
glintformat = GL_ALPHA;
glformat = GL_ALPHA;
}
glintformat = GL_RED;
glformat = GL_RED;
gltype = GL_UNSIGNED_BYTE;
break;
case COGL_PIXEL_FORMAT_G_8:

View File

@@ -98,11 +98,8 @@ _cogl_texture_driver_gen (CoglContext *ctx,
g_assert_not_reached();
}
/* If the driver doesn't support alpha textures directly then we'll
* fake them by setting the swizzle parameters */
if (internal_format == COGL_PIXEL_FORMAT_A_8 &&
!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) &&
_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
/* GL_ALPHA is deprecated; instead, use GL_RED with a swizzle mask */
if (internal_format == COGL_PIXEL_FORMAT_A_8)
{
static const GLint red_swizzle[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED };

View File

@@ -83,8 +83,8 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
switch (format)
{
case COGL_PIXEL_FORMAT_A_8:
glintformat = GL_ALPHA;
glformat = GL_ALPHA;
glintformat = GL_RED;
glformat = GL_RED;
gltype = GL_UNSIGNED_BYTE;
break;
case COGL_PIXEL_FORMAT_G_8:

View File

@@ -12,9 +12,6 @@ cdata.set('COGL_HAS_X11', have_x11)
cdata.set('COGL_HAS_X11_SUPPORT', have_x11)
cdata.set('COGL_HAS_XLIB', have_x11)
cdata.set('COGL_HAS_XLIB_SUPPORT', have_x11)
if have_native_backend
cdata.set('COGL_HAS_LIBDRM', libdrm_dep.found())
endif
cogl_defines_h = configure_file(
input: 'cogl-defines.h.meson',
@@ -306,6 +303,8 @@ cogl_sources = [
'cogl-blend-string.c',
'cogl-blend-string.h',
'cogl-debug.c',
'cogl-trace.c',
'cogl-trace.h',
'cogl-sub-texture-private.h',
'cogl-texture-private.h',
'cogl-texture-2d-private.h',

View File

@@ -7,6 +7,7 @@ cogl_includepath = include_directories('.', 'cogl')
cdata = configuration_data()
cdata.set('HAVE_COGL_GL', have_gl)
cdata.set('HAVE_COGL_GLES2', have_gles2)
cdata.set('HAVE_TRACING', have_profiler)
cdata.set('ENABLE_UNIT_TESTS', have_cogl_tests)
cogl_config_h = configure_file(
@@ -26,6 +27,12 @@ cogl_pkg_private_deps = [
#uprof_dep,
]
if have_profiler
cogl_pkg_private_deps += [
sysprof_dep,
]
endif
if have_wayland
cogl_pkg_deps += [
wayland_server_dep,
@@ -87,19 +94,21 @@ if have_gles2
endif
cogl_debug_c_args = []
if buildtype.startswith('debug')
buildtype = get_option('buildtype')
if get_option('debug')
cogl_debug_c_args += [
'-DCOGL_GL_DEBUG',
'-DCOGL_OBJECT_DEBUG',
'-DCOGL_ENABLE_DEBUG',
'-fno-omit-frame-pointer'
]
elif buildtype == 'release'
elif buildtype != 'plain'
cogl_debug_c_args += [
'-DG_DISABLE_CHECKS',
'-DG_DISABLE_CAST_CHECKS',
'-DG_DISABLE_CAST_CHECKS'
]
endif
supported_cogl_debug_c_args = cc.get_supported_arguments(cogl_debug_c_args)
cogl_c_args += cogl_debug_c_args
if have_cogl_tests

View File

@@ -49,6 +49,9 @@
/* Building with startup notification support */
#mesondefine HAVE_STARTUP_NOTIFICATION
/* Building with Sysprof profiling suport */
#mesondefine HAVE_PROFILER
/* Path to Xwayland executable */
#mesondefine XWAYLAND_PATH

View File

@@ -127,6 +127,14 @@
</description>
</key>
<key name="locate-pointer-key" type="s">
<default>'Control_L'</default>
<summary>Modifier to use to locate the pointer</summary>
<description>
This key will initiate the “locate pointer” action.
</description>
</key>
<child name="keybindings" schema="org.gnome.mutter.keybindings"/>
</schema>

View File

@@ -61,10 +61,17 @@
<key name="xwayland-allow-grabs" type="b">
<default>false</default>
<summary>Allow grabs with Xwayland</summary>
<summary>Allow X11 grabs to lock keyboard focus with Xwayland</summary>
<description>
Allow keyboard grabs issued by X11 applications running in Xwayland
to be taken into account.
Allow all keyboard events to be routed to X11 “override redirect”
windows with a grab when running in Xwayland.
This option is to support X11 clients which map an “override redirect”
window (which do not receive keyboard focus) and issue a keyboard
grab to force all keyboard events to that window.
This option is seldom used and has no effect on regular X11 windows
which can receive keyboard focus under normal circumstances.
For a X11 grab to be taken into account under Wayland, the client must
also either send a specific X11 ClientMessage to the root window or be

View File

@@ -264,6 +264,11 @@ if have_tests
have_installed_tests = get_option('installed_tests')
endif
have_profiler = get_option('profiler')
if have_profiler
sysprof_dep = dependency('sysprof-capture-3')
endif
required_functions = [
'ffs',
'clz',
@@ -276,54 +281,57 @@ endforeach
add_project_arguments('-D_GNU_SOURCE', language: 'c')
all_warnings = [
'-fno-strict-aliasing',
'-Wpointer-arith',
'-Wmissing-declarations',
'-Wimplicit-function-declaration',
'-Wformat=2',
'-Wformat-nonliteral',
'-Wformat-security',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wnested-externs',
'-Wold-style-definition',
'-Wundef',
'-Wunused',
'-Wcast-align',
'-Wmissing-noreturn',
'-Wmissing-format-attribute',
'-Wmissing-include-dirs',
'-Wlogical-op',
'-Wignored-qualifiers',
'-Werror=redundant-decls',
'-Werror=implicit',
'-Werror=nonnull',
'-Werror=init-self',
'-Werror=main',
'-Werror=missing-braces',
'-Werror=sequence-point',
'-Werror=return-type',
'-Werror=trigraphs',
'-Werror=array-bounds',
'-Werror=write-strings',
'-Werror=address',
'-Werror=int-to-pointer-cast',
'-Werror=pointer-to-int-cast',
'-Werror=empty-body',
'-Werror=write-strings',
]
supported_warnings = cc.get_supported_arguments(all_warnings)
add_project_arguments(supported_warnings, language: 'c')
debug_c_args = []
buildtype = get_option('buildtype')
if buildtype.startswith('debug')
debug_c_args += '-DG_ENABLE_DEBUG'
if buildtype != 'plain'
all_warnings = [
'-fno-strict-aliasing',
'-Wpointer-arith',
'-Wmissing-declarations',
'-Wimplicit-function-declaration',
'-Wformat=2',
'-Wformat-nonliteral',
'-Wformat-security',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wnested-externs',
'-Wold-style-definition',
'-Wundef',
'-Wunused',
'-Wcast-align',
'-Wmissing-noreturn',
'-Wmissing-format-attribute',
'-Wmissing-include-dirs',
'-Wlogical-op',
'-Wignored-qualifiers',
'-Werror=redundant-decls',
'-Werror=implicit',
'-Werror=nonnull',
'-Werror=init-self',
'-Werror=main',
'-Werror=missing-braces',
'-Werror=sequence-point',
'-Werror=return-type',
'-Werror=trigraphs',
'-Werror=array-bounds',
'-Werror=write-strings',
'-Werror=address',
'-Werror=int-to-pointer-cast',
'-Werror=pointer-to-int-cast',
'-Werror=empty-body',
'-Werror=write-strings',
]
supported_warnings = cc.get_supported_arguments(all_warnings)
add_project_arguments(supported_warnings, language: 'c')
endif
if get_option('debug')
debug_c_args = [
'-DG_ENABLE_DEBUG',
'-fno-omit-frame-pointer'
]
supported_debug_c_args = cc.get_supported_arguments(debug_c_args)
add_project_arguments(supported_debug_c_args, language: 'c')
endif
add_project_arguments(debug_c_args, language: 'c')
cc.compiles('void main (void) { __builtin_ffsl (0); __builtin_popcountl (0); }')
@@ -343,6 +351,7 @@ cdata.set('HAVE_LIBWACOM', have_libwacom)
cdata.set('HAVE_SM', have_sm)
cdata.set('HAVE_STARTUP_NOTIFICATION', have_startup_notification)
cdata.set('HAVE_INTROSPECTION', have_introspection)
cdata.set('HAVE_PROFILER', have_profiler)
xkb_base = xkeyboard_config_dep.get_pkgconfig_variable('xkb_base')
cdata.set_quoted('XKB_BASE', xkb_base)
@@ -408,6 +417,7 @@ output = [
' SM....................... ' + have_sm.to_string(),
' Startup notification..... ' + have_startup_notification.to_string(),
' Introspection............ ' + have_introspection.to_string(),
' Profiler................. ' + have_profiler.to_string(),
'',
' Tests:',
'',

View File

@@ -123,6 +123,12 @@ option('tests',
description: 'Enable tests globally. Specific test suites can be controlled with core_tests, clutter_tests, and cogl_tests'
)
option('profiler',
type: 'boolean',
value: true,
description: 'Enable Sysprof tracing'
)
option('installed_tests',
type: 'boolean',
value: true,

View File

@@ -9,6 +9,7 @@ data/org.gnome.mutter.gschema.xml.in
data/org.gnome.mutter.wayland.gschema.xml.in
src/backends/meta-input-settings.c
src/backends/meta-monitor-manager.c
src/backends/meta-profiler.c
src/compositor/compositor.c
src/compositor/meta-background.c
src/core/bell.c

View File

@@ -13,8 +13,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter.master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2019-05-15 13:19+0000\n"
"PO-Revision-Date: 2019-05-16 12:38+0200\n"
"POT-Creation-Date: 2019-06-07 19:32+0000\n"
"PO-Revision-Date: 2019-06-11 12:54+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: es <gnome-es-list@gnome.org>\n"
"Language: es\n"
@@ -397,16 +397,6 @@ msgid "Enable experimental features"
msgstr "Activar las características experimentales"
#: data/org.gnome.mutter.gschema.xml.in:108
#| msgid ""
#| "To enable experimental features, add the feature keyword to the list. "
#| "Whether the feature requires restarting the compositor depends on the "
#| "given feature. Any experimental feature is not required to still be "
#| "available, or configurable. Dont expect adding anything in this setting "
#| "to be future proof. Currently possible keywords: • “scale-monitor-"
#| "framebuffer” — makes mutter default to layout logical monitors in a "
#| "logical pixel coordinate space, while scaling monitor framebuffers "
#| "instead of window content, to manage HiDPI monitors. Does not require a "
#| "restart."
msgid ""
"To enable experimental features, add the feature keyword to the list. "
"Whether the feature requires restarting the compositor depends on the given "
@@ -432,19 +422,27 @@ msgstr ""
"planificación en tiempo real con prioridad baja. El ejecutable o el usuario "
"deben tener CAP_SYS_NICE. Requiere reniciar."
#: data/org.gnome.mutter.gschema.xml.in:145
#: data/org.gnome.mutter.gschema.xml.in:132
msgid "Modifier to use to locate the pointer"
msgstr "Modificador que usar para encontrar el puntero"
#: data/org.gnome.mutter.gschema.xml.in:133
msgid "This key will initiate the “locate pointer” action."
msgstr "Esta tecla iniciará la acción de encontrar el puntero."
#: data/org.gnome.mutter.gschema.xml.in:153
msgid "Select window from tab popup"
msgstr "Seleccionar ventana de la pestaña emergente"
#: data/org.gnome.mutter.gschema.xml.in:150
#: data/org.gnome.mutter.gschema.xml.in:158
msgid "Cancel tab popup"
msgstr "Cancelar pestaña emergente"
#: data/org.gnome.mutter.gschema.xml.in:155
#: data/org.gnome.mutter.gschema.xml.in:163
msgid "Switch monitor configurations"
msgstr "Cambiar la configuración del monitor"
#: data/org.gnome.mutter.gschema.xml.in:160
#: data/org.gnome.mutter.gschema.xml.in:168
msgid "Rotates the built-in monitor configuration"
msgstr "Rota la configuración del monitor empotrado"
@@ -501,16 +499,29 @@ msgid "Re-enable shortcuts"
msgstr "Volver a activar los atajos"
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
msgid "Allow grabs with Xwayland"
msgstr "Permitir capturas con Xwayland"
#| msgid "Allow grabs with Xwayland"
msgid "Allow X11 grabs to lock keyboard focus with Xwayland"
msgstr ""
"Permitir capturas con X11 para bloquear el foco del teclado con Xwayland"
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
#, fuzzy
#| msgid ""
#| "Allow keyboard grabs issued by X11 applications running in Xwayland to be "
#| "taken into account. For a X11 grab to be taken into account under "
#| "Wayland, the client must also either send a specific X11 ClientMessage to "
#| "the root window or be among the applications white-listed in key "
#| "“xwayland-grab-access-rules”."
msgid ""
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
"taken into account. For a X11 grab to be taken into account under Wayland, "
"the client must also either send a specific X11 ClientMessage to the root "
"window or be among the applications white-listed in key “xwayland-grab-"
"access-rules”."
"Allow all keyboard events to be routed to X11 “override redirect” windows "
"with a grab when running in Xwayland. This option is to support X11 clients "
"which map an “override redirect” window (which do not receive keyboard "
"focus) and issue a keyboard grab to force all keyboard events to that "
"window. This option is seldom used and has no effect on regular X11 windows "
"which can receive keyboard focus under normal circumstances. For a X11 grab "
"to be taken into account under Wayland, the client must also either send a "
"specific X11 ClientMessage to the root window or be among the applications "
"white-listed in key “xwayland-grab-access-rules”."
msgstr ""
"Permitir que las pulsaciones del teclado emitidas por aplicaciones X11 "
"ejecutándose en XWayland se tengan en cuenta. Para que una pulsación X11 se "
@@ -518,11 +529,11 @@ msgstr ""
"específico de X11 a la ventana raíz o estar en la lista blanca de "
"aplicaciones en la clave “xwayland-grab-access-rules”."
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
msgid "Xwayland applications allowed to issue keyboard grabs"
msgstr "Aplicaciones de Xwayland que pueden capturar el teclado"
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
#: data/org.gnome.mutter.wayland.gschema.xml.in:85
msgid ""
"List the resource names or resource class of X11 windows either allowed or "
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
@@ -548,7 +559,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2426
#: src/backends/meta-input-settings.c:2529
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Cambiar modo (grupo %d)"
@@ -556,11 +567,11 @@ msgstr "Cambiar modo (grupo %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2449
#: src/backends/meta-input-settings.c:2552
msgid "Switch monitor"
msgstr "Cambiar monitor"
#: src/backends/meta-input-settings.c:2451
#: src/backends/meta-input-settings.c:2554
msgid "Show on-screen help"
msgstr "Mostrar la ayuda en pantalla"
@@ -591,9 +602,15 @@ msgctxt ""
msgid "%s %s"
msgstr "%s %s"
#. Translators: this string will appear in Sysprof
#: src/backends/meta-profiler.c:82
#| msgid "Compositing Manager"
msgid "Compositor"
msgstr "Compositor"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:508
#: src/compositor/compositor.c:510
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@@ -699,7 +716,7 @@ msgstr "Imprimir versión"
msgid "Mutter plugin to use"
msgstr "Complemento de mutter que usar"
#: src/core/prefs.c:1786
#: src/core/prefs.c:1834
#, c-format
msgid "Workspace %d"
msgstr "Área de trabajo %d"
@@ -713,7 +730,7 @@ msgstr "Mutter fue compilado sin soporte para modo prolijo\n"
msgid "Mode Switch: Mode %d"
msgstr "Cambiar modo: modo %d"
#: src/x11/meta-x11-display.c:669
#: src/x11/meta-x11-display.c:681
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@@ -722,16 +739,16 @@ msgstr ""
"La pantalla «%s» ya tiene un gestor de ventanas; pruebe a usar la opción «--"
"replace» para reemplazar el gestor de ventanas activo."
#: src/x11/meta-x11-display.c:1011
#: src/x11/meta-x11-display.c:1023
msgid "Failed to initialize GDK\n"
msgstr "Falló al inicializar GDK\n"
#: src/x11/meta-x11-display.c:1035
#: src/x11/meta-x11-display.c:1047
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n"
#: src/x11/meta-x11-display.c:1116
#: src/x11/meta-x11-display.c:1131
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "La ventana %d en la pantalla «%s» no es válida\n"
@@ -2134,9 +2151,6 @@ msgstr "%s (on %s)"
#~ msgid "Commands to run in response to keybindings"
#~ msgstr "Comandos a ejecutar en respuesta a combinaciones de teclas"
#~ msgid "Compositing Manager"
#~ msgstr "Gestor de composición"
#~ msgid "Control how new windows get focus"
#~ msgstr "Controla cómo obtienen el foco las ventanas nuevas"

View File

@@ -6,20 +6,20 @@
# Gabor Sari <saga at externet dot hu>, 2003.
# Laszlo Dvornik <dvornik at gnome dot hu>, 2004.
# Gabor Kelemen <kelemeng at gnome dot hu>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013.
# Balázs Úr <urbalazs at gmail dot com>, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
# Balázs Úr <ur.balazs at fsf dot hu>, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2019-02-04 17:52+0000\n"
"PO-Revision-Date: 2019-02-05 21:06+0100\n"
"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
"POT-Creation-Date: 2019-05-31 18:48+0000\n"
"PO-Revision-Date: 2019-06-01 17:46+0200\n"
"Last-Translator: Balázs Úr <ur.balazs at fsf dot hu>\n"
"Language-Team: Hungarian <gnome-hu-list at gnome dot org>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 1.2\n"
"X-Generator: Lokalize 18.12.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: data/50-mutter-navigation.xml:6
@@ -395,7 +395,9 @@ msgid ""
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
"mutter default to layout logical monitors in a logical pixel coordinate "
"space, while scaling monitor framebuffers instead of window content, to "
"manage HiDPI monitors. Does not require a restart."
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
"mutter request a low priority real-time scheduling. The executable or user "
"must have CAP_SYS_NICE. Requires a restart."
msgstr ""
"A kísérleti funkciók engedélyezéséhez adja hozzá a funkció kulcsszavát a "
"listához. A funkció a betűszedő újraindítását igényelheti az adott "
@@ -406,21 +408,23 @@ msgstr ""
"teszi a mutter programot a logikai monitorok elrendezéséhez egy logikai "
"képpontkoordináta-térben, miközben átméretezi a monitor keretpufferét az "
"ablaktartalom helyett azért, hogy kezelje a HiDPI monitorokat. Nem igényel "
"újraindítást."
"újraindítást. • „rt-scheduler” — alacsony prioritású, valós idejű ütemezésre "
"kéri a mutter programot. A programnak vagy a felhasználónak CAP_SYS_NICE "
"értékkel kell rendelkeznie. Újraindítást igényel."
#: data/org.gnome.mutter.gschema.xml.in:141
#: data/org.gnome.mutter.gschema.xml.in:145
msgid "Select window from tab popup"
msgstr "Ablakok kiválasztása tab billentyűre felugró ablakból"
#: data/org.gnome.mutter.gschema.xml.in:146
#: data/org.gnome.mutter.gschema.xml.in:150
msgid "Cancel tab popup"
msgstr "Tab felugró kikapcsolása"
#: data/org.gnome.mutter.gschema.xml.in:151
#: data/org.gnome.mutter.gschema.xml.in:155
msgid "Switch monitor configurations"
msgstr "Monitorkonfiguráció átváltása"
#: data/org.gnome.mutter.gschema.xml.in:156
#: data/org.gnome.mutter.gschema.xml.in:160
msgid "Rotates the built-in monitor configuration"
msgstr "Cserélgeti a beépített monitorkonfigurációkat"
@@ -525,7 +529,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2423
#: src/backends/meta-input-settings.c:2426
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Módkapcsoló (%d. csoport)"
@@ -533,34 +537,34 @@ msgstr "Módkapcsoló (%d. csoport)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2446
#: src/backends/meta-input-settings.c:2449
msgid "Switch monitor"
msgstr "Monitorváltás"
#: src/backends/meta-input-settings.c:2448
#: src/backends/meta-input-settings.c:2451
msgid "Show on-screen help"
msgstr "Képernyősúgó megjelenítése"
#: src/backends/meta-monitor-manager.c:954
#: src/backends/meta-monitor-manager.c:976
msgid "Built-in display"
msgstr "Beépített kijelző"
#: src/backends/meta-monitor-manager.c:986
#: src/backends/meta-monitor-manager.c:1008
msgid "Unknown"
msgstr "Ismeretlen"
#: src/backends/meta-monitor-manager.c:988
#: src/backends/meta-monitor-manager.c:1010
msgid "Unknown Display"
msgstr "Ismeretlen kijelző"
#: src/backends/meta-monitor-manager.c:996
#: src/backends/meta-monitor-manager.c:1018
#, c-format
msgctxt ""
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
msgid "%s %s"
msgstr "%s %s"
#: src/backends/meta-monitor-manager.c:1004
#: src/backends/meta-monitor-manager.c:1026
#, c-format
msgctxt ""
"This is a monitor vendor name followed by product/model name where size in "
@@ -568,9 +572,14 @@ msgctxt ""
msgid "%s %s"
msgstr "%s %s"
#. Translators: this string will appear in Sysprof
#: src/backends/meta-profiler.c:82
msgid "Compositor"
msgstr "Betűszedő"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:482
#: src/compositor/compositor.c:510
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@@ -578,7 +587,7 @@ msgstr ""
"Már fut egy másik kompozitálás-kezelő a(z) %i. képernyőn a(z) „%s” "
"megjelenítőn."
#: src/core/bell.c:252
#: src/core/bell.c:192
msgid "Bell event"
msgstr "Csengetés esemény"
@@ -628,16 +637,16 @@ msgid "Run with X11 backend"
msgstr "Futtatás X11 háttérprogrammal"
#. Translators: %s is a window title
#: src/core/meta-close-dialog-default.c:150
#: src/core/meta-close-dialog-default.c:151
#, c-format
msgid "“%s” is not responding."
msgstr "„%s” nem válaszol."
#: src/core/meta-close-dialog-default.c:152
#: src/core/meta-close-dialog-default.c:153
msgid "Application is not responding."
msgstr "Az alkalmazás nem válaszol."
#: src/core/meta-close-dialog-default.c:157
#: src/core/meta-close-dialog-default.c:158
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@@ -645,11 +654,11 @@ msgstr ""
"Várhat egy kicsit a folytatódására, vagy kikényszerítheti az alkalmazás "
"teljes kilépését."
#: src/core/meta-close-dialog-default.c:164
#: src/core/meta-close-dialog-default.c:165
msgid "_Force Quit"
msgstr "_Erőltetett kilépés"
#: src/core/meta-close-dialog-default.c:164
#: src/core/meta-close-dialog-default.c:165
msgid "_Wait"
msgstr "Vá_rakozás"
@@ -690,7 +699,7 @@ msgstr "A Mutter ablakkezelőt a részletes mód támogatása nélkül fordítot
msgid "Mode Switch: Mode %d"
msgstr "Módkapcsoló: %d. mód"
#: src/x11/meta-x11-display.c:666
#: src/x11/meta-x11-display.c:674
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@@ -699,20 +708,25 @@ msgstr ""
"A(z) „%s” kijelző már rendelkezik ablakkezelővel; próbálja a --replace "
"kapcsolóval helyettesíteni a jelenlegi ablakkezelőt."
#: src/x11/meta-x11-display.c:1008
#: src/x11/meta-x11-display.c:1016
msgid "Failed to initialize GDK\n"
msgstr "A GDK előkészítése meghiúsult\n"
#: src/x11/meta-x11-display.c:1032
#: src/x11/meta-x11-display.c:1040
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "Nem sikerült megnyitni a(z) „%s” X Window rendszer képernyőt\n"
#: src/x11/meta-x11-display.c:1115
#: src/x11/meta-x11-display.c:1124
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "A(z) %d. képernyő a(z) „%s” megjelenítőn érvénytelen\n"
#: src/x11/meta-x11-selection-input-stream.c:445
#, c-format
msgid "Format %s not supported"
msgstr "A(z) %s formátum nem támogatott"
#: src/x11/session.c:1821
msgid ""
"These windows do not support “save current setup” and will have to be "
@@ -721,8 +735,7 @@ msgstr ""
"Az alábbi ablakok nem támogatják az „aktuális beállítások mentését”, emiatt "
"ezeket a legközelebbi bejelentkezéskor manuálisan újra kell indítania."
#: src/x11/window-props.c:568
#: src/x11/window-props.c:569
#, c-format
msgid "%s (on %s)"
msgstr "%s (ezen: %s)"

View File

@@ -66,6 +66,10 @@
#include "meta/meta-backend.h"
#include "meta/util.h"
#ifdef HAVE_PROFILER
#include "backends/meta-profiler.h"
#endif
#ifdef HAVE_REMOTE_DESKTOP
#include "backends/meta-dbus-session-watcher.h"
#include "backends/meta-remote-access-controller-private.h"
@@ -127,6 +131,10 @@ struct _MetaBackendPrivate
MetaRemoteDesktop *remote_desktop;
#endif
#ifdef HAVE_PROFILER
MetaProfiler *profiler;
#endif
ClutterBackend *clutter_backend;
ClutterActor *stage;
@@ -193,6 +201,10 @@ meta_backend_finalize (GObject *object)
g_clear_object (&priv->settings);
#ifdef HAVE_PROFILER
g_clear_object (&priv->profiler);
#endif
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
@@ -841,6 +853,10 @@ meta_backend_initable_init (GInitable *initable,
system_bus_gotten_cb,
backend);
#ifdef HAVE_PROFILER
priv->profiler = meta_profiler_new ();
#endif
return TRUE;
}

View File

@@ -30,6 +30,7 @@
#include "backends/meta-stage-private.h"
#include "clutter/clutter.h"
#include "clutter/clutter-mutter.h"
#include "cogl/cogl.h"
#include "meta/meta-backend.h"
#include "meta/util.h"
@@ -82,6 +83,33 @@ meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
g_signal_emit (renderer, signals[CURSOR_PAINTED], 0, cursor_sprite);
}
static void
align_cursor_position (MetaCursorRenderer *renderer,
ClutterRect *rect)
{
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
ClutterStageView *view;
cairo_rectangle_int_t view_layout;
float view_scale;
view = clutter_stage_get_view_at (CLUTTER_STAGE (stage),
priv->current_x,
priv->current_y);
if (!view)
return;
clutter_stage_view_get_layout (view, &view_layout);
view_scale = clutter_stage_view_get_scale (view);
clutter_rect_offset (rect, -view_layout.x, -view_layout.y);
rect->origin.x = floorf (rect->origin.x * view_scale) / view_scale;
rect->origin.y = floorf (rect->origin.y * view_scale) / view_scale;
clutter_rect_offset (rect, view_layout.x, view_layout.y);
}
static void
queue_redraw (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
@@ -92,13 +120,16 @@ queue_redraw (MetaCursorRenderer *renderer,
CoglTexture *texture;
ClutterRect rect = CLUTTER_RECT_INIT_ZERO;
if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
/* During early initialization, we can have no stage */
if (!stage)
return;
if (cursor_sprite)
{
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
align_cursor_position (renderer, &rect);
}
if (!priv->stage_overlay)
priv->stage_overlay = meta_stage_create_cursor_overlay (META_STAGE (stage));

View File

@@ -76,7 +76,8 @@ struct _MetaInputSettingsPrivate
GSettings *trackball_settings;
GSettings *keyboard_settings;
GSettings *gsd_settings;
GSettings *a11y_settings;
GSettings *keyboard_a11y_settings;
GSettings *mouse_a11y_settings;
GHashTable *mappable_devices;
@@ -161,7 +162,8 @@ meta_input_settings_dispose (GObject *object)
g_clear_object (&priv->trackball_settings);
g_clear_object (&priv->keyboard_settings);
g_clear_object (&priv->gsd_settings);
g_clear_object (&priv->a11y_settings);
g_clear_object (&priv->keyboard_a11y_settings);
g_clear_object (&priv->mouse_a11y_settings);
g_clear_object (&priv->input_mapper);
g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
g_clear_pointer (&priv->current_tools, g_hash_table_unref);
@@ -1191,10 +1193,10 @@ apply_mappable_device_settings (MetaInputSettings *input_settings,
}
}
struct _a11y_settings_flags_pair {
struct _keyboard_a11y_settings_flags_pair {
const char *name;
ClutterKeyboardA11yFlags flag;
} settings_flags_pair[] = {
} keyboard_a11y_settings_flags_pair[] = {
{ "enable", CLUTTER_A11Y_KEYBOARD_ENABLED },
{ "timeout-enable", CLUTTER_A11Y_TIMEOUT_ENABLED },
{ "mousekeys-enable", CLUTTER_A11Y_MOUSE_KEYS_ENABLED },
@@ -1225,23 +1227,23 @@ load_keyboard_a11y_settings (MetaInputSettings *input_settings,
return;
kbd_a11y_settings.controls = 0;
for (i = 0; i < G_N_ELEMENTS (settings_flags_pair); i++)
for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++)
{
if (g_settings_get_boolean (priv->a11y_settings, settings_flags_pair[i].name))
kbd_a11y_settings.controls |= settings_flags_pair[i].flag;
if (g_settings_get_boolean (priv->keyboard_a11y_settings, keyboard_a11y_settings_flags_pair[i].name))
kbd_a11y_settings.controls |= keyboard_a11y_settings_flags_pair[i].flag;
}
kbd_a11y_settings.timeout_delay = g_settings_get_int (priv->a11y_settings,
kbd_a11y_settings.timeout_delay = g_settings_get_int (priv->keyboard_a11y_settings,
"disable-timeout");
kbd_a11y_settings.slowkeys_delay = g_settings_get_int (priv->a11y_settings,
kbd_a11y_settings.slowkeys_delay = g_settings_get_int (priv->keyboard_a11y_settings,
"slowkeys-delay");
kbd_a11y_settings.debounce_delay = g_settings_get_int (priv->a11y_settings,
kbd_a11y_settings.debounce_delay = g_settings_get_int (priv->keyboard_a11y_settings,
"bouncekeys-delay");
kbd_a11y_settings.mousekeys_init_delay = g_settings_get_int (priv->a11y_settings,
kbd_a11y_settings.mousekeys_init_delay = g_settings_get_int (priv->keyboard_a11y_settings,
"mousekeys-init-delay");
kbd_a11y_settings.mousekeys_max_speed = g_settings_get_int (priv->a11y_settings,
kbd_a11y_settings.mousekeys_max_speed = g_settings_get_int (priv->keyboard_a11y_settings,
"mousekeys-max-speed");
kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->a11y_settings,
kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->keyboard_a11y_settings,
"mousekeys-accel-time");
clutter_device_manager_set_kbd_a11y_settings (priv->device_manager, &kbd_a11y_settings);
@@ -1256,25 +1258,121 @@ on_keyboard_a11y_settings_changed (ClutterDeviceManager *device_manager,
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
guint i;
for (i = 0; i < G_N_ELEMENTS (settings_flags_pair); i++)
for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++)
{
if (settings_flags_pair[i].flag & what_changed)
g_settings_set_boolean (priv->a11y_settings,
settings_flags_pair[i].name,
(new_flags & settings_flags_pair[i].flag) ? TRUE : FALSE);
if (keyboard_a11y_settings_flags_pair[i].flag & what_changed)
g_settings_set_boolean (priv->keyboard_a11y_settings,
keyboard_a11y_settings_flags_pair[i].name,
(new_flags & keyboard_a11y_settings_flags_pair[i].flag) ? TRUE : FALSE);
}
}
static void
meta_input_a11y_settings_changed (GSettings *settings,
const char *key,
gpointer user_data)
meta_input_keyboard_a11y_settings_changed (GSettings *settings,
const char *key,
gpointer user_data)
{
MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
load_keyboard_a11y_settings (input_settings, NULL);
}
struct _pointer_a11y_settings_flags_pair {
const char *name;
ClutterPointerA11yFlags flag;
} pointer_a11y_settings_flags_pair[] = {
{ "secondary-click-enabled", CLUTTER_A11Y_SECONDARY_CLICK_ENABLED },
{ "dwell-click-enabled", CLUTTER_A11Y_DWELL_ENABLED },
};
static ClutterPointerA11yDwellDirection
pointer_a11y_dwell_direction_from_setting (MetaInputSettings *input_settings,
const char *key)
{
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
GDesktopMouseDwellDirection dwell_gesture_direction;
dwell_gesture_direction = g_settings_get_enum (priv->mouse_a11y_settings, key);
switch (dwell_gesture_direction)
{
case G_DESKTOP_MOUSE_DWELL_DIRECTION_LEFT:
return CLUTTER_A11Y_DWELL_DIRECTION_LEFT;
break;
case G_DESKTOP_MOUSE_DWELL_DIRECTION_RIGHT:
return CLUTTER_A11Y_DWELL_DIRECTION_RIGHT;
break;
case G_DESKTOP_MOUSE_DWELL_DIRECTION_UP:
return CLUTTER_A11Y_DWELL_DIRECTION_UP;
break;
case G_DESKTOP_MOUSE_DWELL_DIRECTION_DOWN:
return CLUTTER_A11Y_DWELL_DIRECTION_DOWN;
break;
default:
break;
}
return CLUTTER_A11Y_DWELL_DIRECTION_NONE;
}
static void
load_pointer_a11y_settings (MetaInputSettings *input_settings,
ClutterInputDevice *device)
{
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
ClutterPointerA11ySettings pointer_a11y_settings;
ClutterInputDevice *core_pointer;
GDesktopMouseDwellMode dwell_mode;
guint i;
core_pointer = clutter_device_manager_get_core_device (priv->device_manager, CLUTTER_POINTER_DEVICE);
if (device && device != core_pointer)
return;
clutter_device_manager_get_pointer_a11y_settings (priv->device_manager, &pointer_a11y_settings);
pointer_a11y_settings.controls = 0;
for (i = 0; i < G_N_ELEMENTS (pointer_a11y_settings_flags_pair); i++)
{
if (g_settings_get_boolean (priv->mouse_a11y_settings, pointer_a11y_settings_flags_pair[i].name))
pointer_a11y_settings.controls |= pointer_a11y_settings_flags_pair[i].flag;
}
/* "secondary-click-time" is expressed in seconds */
pointer_a11y_settings.secondary_click_delay =
(1000 * g_settings_get_double (priv->mouse_a11y_settings, "secondary-click-time"));
/* "dwell-time" is expressed in seconds */
pointer_a11y_settings.dwell_delay =
(1000 * g_settings_get_double (priv->mouse_a11y_settings, "dwell-time"));
pointer_a11y_settings.dwell_threshold = g_settings_get_int (priv->mouse_a11y_settings,
"dwell-threshold");
dwell_mode = g_settings_get_enum (priv->mouse_a11y_settings, "dwell-mode");
if (dwell_mode == G_DESKTOP_MOUSE_DWELL_MODE_WINDOW)
pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_WINDOW;
else
pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_GESTURE;
pointer_a11y_settings.dwell_gesture_single =
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-single");
pointer_a11y_settings.dwell_gesture_double =
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-double");
pointer_a11y_settings.dwell_gesture_drag =
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-drag");
pointer_a11y_settings.dwell_gesture_secondary =
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-secondary");
clutter_device_manager_set_pointer_a11y_settings (priv->device_manager, &pointer_a11y_settings);
}
static void
meta_input_mouse_a11y_settings_changed (GSettings *settings,
const char *key,
gpointer user_data)
{
MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
load_pointer_a11y_settings (input_settings, NULL);
}
static GSettings *
lookup_device_settings (ClutterInputDevice *device)
{
@@ -1556,6 +1654,7 @@ apply_device_settings (MetaInputSettings *input_settings,
priv->trackball_settings,
device);
load_keyboard_a11y_settings (input_settings, device);
load_pointer_a11y_settings (input_settings, device);
}
static void
@@ -1856,12 +1955,16 @@ meta_input_settings_init (MetaInputSettings *settings)
clutter_settings_get_default(), "double-click-time",
G_SETTINGS_BIND_GET);
priv->a11y_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard");
g_signal_connect (priv->a11y_settings, "changed",
G_CALLBACK (meta_input_a11y_settings_changed), settings);
priv->keyboard_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard");
g_signal_connect (priv->keyboard_a11y_settings, "changed",
G_CALLBACK (meta_input_keyboard_a11y_settings_changed), settings);
g_signal_connect (priv->device_manager, "kbd-a11y-flags-changed",
G_CALLBACK (on_keyboard_a11y_settings_changed), settings);
priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse");
g_signal_connect (priv->mouse_a11y_settings, "changed",
G_CALLBACK (meta_input_mouse_a11y_settings_changed), settings);
priv->mappable_devices =
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free);

View File

@@ -0,0 +1,206 @@
/*
* Copyright (C) 2019 Endless, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include "src/backends/meta-profiler.h"
#include <glib-unix.h>
#include <glib/gi18n.h>
#include <gio/gunixfdlist.h>
#include "cogl/cogl-trace.h"
#define META_SYSPROF_PROFILER_DBUS_PATH "/org/gnome/Sysprof3/Profiler"
struct _MetaProfiler
{
MetaDBusSysprof3ProfilerSkeleton parent_instance;
GDBusConnection *connection;
GCancellable *cancellable;
gboolean running;
};
static void
meta_sysprof_capturer_init_iface (MetaDBusSysprof3ProfilerIface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaProfiler,
meta_profiler,
META_DBUS_TYPE_SYSPROF3_PROFILER_SKELETON,
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SYSPROF3_PROFILER,
meta_sysprof_capturer_init_iface))
static gboolean
handle_start (MetaDBusSysprof3Profiler *dbus_profiler,
GDBusMethodInvocation *invocation,
GVariant *options,
GVariant *fd_variant)
{
MetaProfiler *profiler = META_PROFILER (dbus_profiler);
GMainContext *main_context = g_main_context_default ();
GDBusMessage *message;
GUnixFDList *fd_list;
const char *group_name;
int position;
int fd = -1;
if (profiler->running)
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Profiler already running");
return TRUE;
}
g_variant_get (fd_variant, "h", &position);
message = g_dbus_method_invocation_get_message (invocation);
fd_list = g_dbus_message_get_unix_fd_list (message);
if (fd_list)
fd = g_unix_fd_list_get (fd_list, position, NULL);
/* Translators: this string will appear in Sysprof */
group_name = _("Compositor");
if (fd != -1)
{
cogl_set_tracing_enabled_on_thread_with_fd (main_context,
group_name,
fd);
}
else
{
cogl_set_tracing_enabled_on_thread (main_context,
group_name,
"mutter-profile.syscap");
}
profiler->running = TRUE;
g_debug ("Profiler running");
meta_dbus_sysprof3_profiler_complete_start (dbus_profiler, invocation);
return TRUE;
}
static gboolean
handle_stop (MetaDBusSysprof3Profiler *dbus_profiler,
GDBusMethodInvocation *invocation)
{
MetaProfiler *profiler = META_PROFILER (dbus_profiler);
if (!profiler->running)
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Profiler not running");
return TRUE;
}
cogl_set_tracing_disabled_on_thread (g_main_context_default ());
profiler->running = FALSE;
g_debug ("Stopping profiler");
meta_dbus_sysprof3_profiler_complete_stop (dbus_profiler, invocation);
return TRUE;
}
static void
meta_sysprof_capturer_init_iface (MetaDBusSysprof3ProfilerIface *iface)
{
iface->handle_start = handle_start;
iface->handle_stop = handle_stop;
}
static void
on_bus_acquired_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
g_autoptr (GDBusConnection) connection = NULL;
GDBusInterfaceSkeleton *interface_skeleton;
g_autoptr (GError) error = NULL;
MetaProfiler *profiler;
connection = g_bus_get_finish (result, &error);
if (error)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to get session bus: %s\n", error->message);
return;
}
profiler = META_PROFILER (user_data);
interface_skeleton = G_DBUS_INTERFACE_SKELETON (profiler);
if (!g_dbus_interface_skeleton_export (interface_skeleton,
connection,
META_SYSPROF_PROFILER_DBUS_PATH,
&error))
{
g_warning ("Failed to export profiler object: %s\n", error->message);
return;
}
profiler->connection = g_steal_pointer (&connection);
}
static void
meta_profiler_finalize (GObject *object)
{
MetaProfiler *self = (MetaProfiler *)object;
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->connection);
G_OBJECT_CLASS (meta_profiler_parent_class)->finalize (object);
}
static void
meta_profiler_class_init (MetaProfilerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_profiler_finalize;
}
static void
meta_profiler_init (MetaProfiler *self)
{
self->cancellable = g_cancellable_new ();
g_bus_get (G_BUS_TYPE_SESSION,
self->cancellable,
on_bus_acquired_cb,
self);
}
MetaProfiler *
meta_profiler_new (void)
{
return g_object_new (META_TYPE_PROFILER, NULL);
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2019 Endless, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_PROFILER_H
#define META_PROFILER_H
#include <glib-object.h>
#include "meta-dbus-sysprof3-profiler.h"
G_BEGIN_DECLS
#define META_TYPE_PROFILER (meta_profiler_get_type())
G_DECLARE_FINAL_TYPE (MetaProfiler,
meta_profiler,
META,
PROFILER,
MetaDBusSysprof3ProfilerSkeleton)
MetaProfiler * meta_profiler_new (void);
G_END_DECLS
#endif /* META_PROFILER_H */

View File

@@ -66,6 +66,6 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings,
GPtrArray **whitelist_patterns,
GPtrArray **blacklist_patterns);
gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings);
gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings);
#endif /* META_SETTINGS_PRIVATE_H */

View File

@@ -404,7 +404,7 @@ meta_settings_get_xwayland_grab_patterns (MetaSettings *settings,
}
gboolean
meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings)
meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings)
{
return (settings->xwayland_allow_grabs);
}

View File

@@ -73,6 +73,11 @@
#define EGL_DRM_MASTER_FD_EXT 0x333C
#endif
/* added in libdrm 2.4.95 */
#ifndef DRM_FORMAT_INVALID
#define DRM_FORMAT_INVALID 0
#endif
enum
{
PROP_0,
@@ -247,6 +252,11 @@ static void
free_next_secondary_bo (MetaGpuKms *gpu_kms,
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state);
static gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components);
static MetaBackend *
backend_from_renderer_native (MetaRendererNative *renderer_native)
{
@@ -2116,6 +2126,77 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
}
}
static MetaDumbBuffer *
secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
{
MetaDumbBuffer *current_dumb_fb;
current_dumb_fb = secondary_gpu_state->cpu.dumb_fb;
if (current_dumb_fb == &secondary_gpu_state->cpu.dumb_fbs[0])
return &secondary_gpu_state->cpu.dumb_fbs[1];
else
return &secondary_gpu_state->cpu.dumb_fbs[0];
}
typedef struct _PixelFormatMap {
uint32_t drm_format;
CoglPixelFormat cogl_format;
CoglTextureComponents cogl_components;
} PixelFormatMap;
static const PixelFormatMap pixel_format_map[] = {
/* DRM formats are defined as little-endian, not machine endian. */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
{ DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#elif G_BYTE_ORDER == G_BIG_ENDIAN
/* DRM_FORMAT_RGB565 cannot be expressed. */
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
#else
#error "unexpected G_BYTE_ORDER"
#endif
};
static gboolean
cogl_pixel_format_from_drm_format (uint32_t drm_format,
CoglPixelFormat *out_format,
CoglTextureComponents *out_components)
{
const size_t n = G_N_ELEMENTS (pixel_format_map);
size_t i;
for (i = 0; i < n; i++)
{
if (pixel_format_map[i].drm_format == drm_format)
break;
}
if (i == n)
return FALSE;
if (out_format)
*out_format = pixel_format_map[i].cogl_format;
if (out_components)
*out_components = pixel_format_map[i].cogl_components;
return TRUE;
}
static void
copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
@@ -2123,47 +2204,28 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *cogl_context = framebuffer->context;
int width, height;
uint8_t *target_data;
int target_stride_bytes;
uint32_t target_fb_id;
uint32_t target_drm_format;
MetaDumbBuffer *next_dumb_fb;
MetaDumbBuffer *current_dumb_fb;
MetaDumbBuffer *dumb_fb;
CoglBitmap *dumb_bitmap;
CoglPixelFormat cogl_format;
gboolean ret;
MetaDrmBufferDumb *buffer_dumb;
width = cogl_framebuffer_get_width (framebuffer);
height = cogl_framebuffer_get_height (framebuffer);
dumb_fb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
current_dumb_fb = secondary_gpu_state->cpu.dumb_fb;
if (current_dumb_fb == &secondary_gpu_state->cpu.dumb_fbs[0])
next_dumb_fb = &secondary_gpu_state->cpu.dumb_fbs[1];
else
next_dumb_fb = &secondary_gpu_state->cpu.dumb_fbs[0];
secondary_gpu_state->cpu.dumb_fb = next_dumb_fb;
g_assert (cogl_framebuffer_get_width (framebuffer) == dumb_fb->width);
g_assert (cogl_framebuffer_get_height (framebuffer) == dumb_fb->height);
g_assert (width == secondary_gpu_state->cpu.dumb_fb->width);
g_assert (height == secondary_gpu_state->cpu.dumb_fb->height);
target_data = secondary_gpu_state->cpu.dumb_fb->map;
target_stride_bytes = secondary_gpu_state->cpu.dumb_fb->stride_bytes;
target_fb_id = secondary_gpu_state->cpu.dumb_fb->fb_id;
target_drm_format = secondary_gpu_state->cpu.dumb_fb->drm_format;
ret = cogl_pixel_format_from_drm_format (target_drm_format,
ret = cogl_pixel_format_from_drm_format (dumb_fb->drm_format,
&cogl_format,
NULL);
g_assert (ret);
dumb_bitmap = cogl_bitmap_new_for_data (cogl_context,
width,
height,
dumb_fb->width,
dumb_fb->height,
cogl_format,
target_stride_bytes,
target_data);
dumb_fb->stride_bytes,
dumb_fb->map);
if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
0 /* x */,
@@ -2175,8 +2237,9 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
cogl_object_unref (dumb_bitmap);
g_clear_object (&secondary_gpu_state->gbm.next_fb);
buffer_dumb = meta_drm_buffer_dumb_new (target_fb_id);
buffer_dumb = meta_drm_buffer_dumb_new (dumb_fb->fb_id);
secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_dumb);
secondary_gpu_state->cpu.dumb_fb = dumb_fb;
}
static void

View File

@@ -71,4 +71,6 @@ MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *composito
MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_locate_pointer (MetaCompositor *compositor);
#endif /* META_COMPOSITOR_PRIVATE_H */

View File

@@ -431,13 +431,11 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
{
MetaDisplay *display = compositor->display;
MetaBackend *backend = meta_get_backend ();
MetaWindow *grab_window = display->grab_window;
MetaGrabOp grab_op = display->grab_op;
g_return_if_fail (is_modal (display));
g_signal_emit_by_name (display, "grab-op-end",
meta_plugin_get_display (plugin),
display->grab_window, display->grab_op);
display->grab_op = META_GRAB_OP_NONE;
display->event_route = META_EVENT_ROUTE_NORMAL;
display->grab_window = NULL;
@@ -454,6 +452,10 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
meta_display_sync_wayland_input_focus (display);
}
#endif
g_signal_emit_by_name (display, "grab-op-end",
meta_plugin_get_display (plugin),
grab_window, grab_op);
}
static void
@@ -1551,3 +1553,9 @@ meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor,
return meta_plugin_manager_create_inhibit_shortcuts_dialog (compositor->plugin_mgr,
window);
}
void
meta_compositor_locate_pointer (MetaCompositor *compositor)
{
meta_plugin_manager_locate_pointer (compositor->plugin_mgr);
}

View File

@@ -405,3 +405,13 @@ meta_plugin_manager_create_inhibit_shortcuts_dialog (MetaPluginManager *plugin_m
return meta_inhibit_shortcuts_dialog_default_new (window);
}
void
meta_plugin_manager_locate_pointer (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->locate_pointer)
klass->locate_pointer (plugin);
}

View File

@@ -100,4 +100,6 @@ MetaInhibitShortcutsDialog *
meta_plugin_manager_create_inhibit_shortcuts_dialog (MetaPluginManager *plugin_mgr,
MetaWindow *window);
void meta_plugin_manager_locate_pointer (MetaPluginManager *mgr);
#endif

View File

@@ -2132,8 +2132,8 @@ meta_rectangle_from_clutter_rect (ClutterRect *rect,
*dest = (MetaRectangle) {
.x = ceilf (rect->origin.x),
.y = ceilf (rect->origin.y),
.width = floorf (rect->origin.x + rect->size.width) - dest->x,
.height = floorf (rect->origin.y + rect->size.height) - dest->x,
.width = floorf (rect->size.width),
.height = floorf (rect->size.height),
};
}
break;

View File

@@ -956,10 +956,6 @@ meta_display_close (MetaDisplay *display,
g_clear_object (&display->gesture_tracker);
g_clear_object (&display->stack);
g_clear_pointer (&display->stack_tracker,
meta_stack_tracker_free);
if (display->focus_timeout_id)
g_source_remove (display->focus_timeout_id);
display->focus_timeout_id = 0;
@@ -976,17 +972,21 @@ meta_display_close (MetaDisplay *display,
/* Stop caring about events */
meta_display_free_events (display);
if (display->compositor)
meta_compositor_destroy (display->compositor);
meta_display_shutdown_x11 (display);
g_clear_object (&display->stack);
g_clear_pointer (&display->stack_tracker,
meta_stack_tracker_free);
/* Must be after all calls to meta_window_unmanage() since they
* unregister windows
*/
g_hash_table_destroy (display->wayland_windows);
g_hash_table_destroy (display->stamps);
if (display->compositor)
meta_compositor_destroy (display->compositor);
meta_display_shutdown_x11 (display);
meta_display_shutdown_keys (display);
g_clear_object (&display->bell);
@@ -1837,9 +1837,6 @@ meta_display_end_grab_op (MetaDisplay *display,
g_assert (grab_window != NULL);
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display, grab_window, grab_op);
/* We need to reset this early, since the
* meta_window_grab_op_ended callback relies on this being
* up to date. */
@@ -1891,6 +1888,9 @@ meta_display_end_grab_op (MetaDisplay *display,
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display, grab_window, grab_op);
}
/**

View File

@@ -113,6 +113,9 @@ typedef struct
MetaKeyCombo overlay_key_combo;
MetaResolvedKeyCombo overlay_resolved_key_combo;
gboolean overlay_key_only_pressed;
MetaKeyCombo locate_pointer_key_combo;
MetaResolvedKeyCombo locate_pointer_resolved_key_combo;
gboolean locate_pointer_key_only_pressed;
MetaResolvedKeyCombo iso_next_group_combo[2];
int n_iso_next_group_combos;
@@ -149,6 +152,7 @@ gboolean meta_prefs_remove_keybinding (const char *name);
GList *meta_prefs_get_keybindings (void);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
void meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void);
void meta_x11_display_grab_keys (MetaX11Display *x11_display);

View File

@@ -33,6 +33,7 @@
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-manager-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "compositor/compositor-private.h"
#include "core/edge-resistance.h"
#include "core/frame.h"
#include "core/keybindings-private.h"
@@ -780,6 +781,10 @@ reload_combos (MetaKeyBindingManager *keys)
&keys->overlay_key_combo,
&keys->overlay_resolved_key_combo);
resolve_key_combo (keys,
&keys->locate_pointer_key_combo,
&keys->locate_pointer_resolved_key_combo);
reload_iso_next_group_combos (keys);
g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys);
@@ -871,6 +876,9 @@ rebuild_special_bindings (MetaKeyBindingManager *keys)
meta_prefs_get_overlay_binding (&combo);
keys->overlay_key_combo = combo;
meta_prefs_get_locate_pointer_binding (&combo);
keys->locate_pointer_key_combo = combo;
}
static void
@@ -1062,6 +1070,10 @@ get_keybinding_action (MetaKeyBindingManager *keys,
&keys->overlay_resolved_key_combo))
return META_KEYBINDING_ACTION_OVERLAY_KEY;
if (resolved_key_combo_intersect (resolved_combo,
&keys->locate_pointer_resolved_key_combo))
return META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
binding = get_keybinding (keys, resolved_combo);
if (binding)
{
@@ -1487,6 +1499,10 @@ meta_x11_display_change_keygrabs (MetaX11Display *x11_display,
meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->overlay_resolved_key_combo);
if (keys->locate_pointer_resolved_key_combo.len != 0)
meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->locate_pointer_resolved_key_combo);
for (i = 0; i < keys->n_iso_next_group_combos; i++)
meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->iso_next_group_combo[i]);
@@ -1952,37 +1968,31 @@ process_event (MetaDisplay *display,
}
static gboolean
process_overlay_key (MetaDisplay *display,
ClutterKeyEvent *event,
MetaWindow *window)
process_special_modifier_key (MetaDisplay *display,
ClutterKeyEvent *event,
MetaWindow *window,
gboolean *modifier_press_only,
MetaResolvedKeyCombo *resolved_key_combo,
GFunc trigger_callback)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaBackend *backend = keys->backend;
Display *xdisplay;
if (display->focus_window && !keys->overlay_key_only_pressed)
{
ClutterInputDevice *source;
source = clutter_event_get_source_device ((ClutterEvent *) event);
if (meta_window_shortcuts_inhibited (display->focus_window, source))
return FALSE;
}
if (META_IS_BACKEND_X11 (backend))
xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
else
xdisplay = NULL;
if (keys->overlay_key_only_pressed)
if (*modifier_press_only)
{
if (! resolved_key_combo_has_keycode (&keys->overlay_resolved_key_combo,
if (! resolved_key_combo_has_keycode (resolved_key_combo,
event->hardware_keycode))
{
keys->overlay_key_only_pressed = FALSE;
*modifier_press_only = FALSE;
/* OK, the user hit modifier+key rather than pressing and
* releasing the ovelay key. We want to handle the key
* releasing the modifier key alone. We want to handle the key
* sequence "normally". Unfortunately, using
* XAllowEvents(..., ReplayKeyboard, ...) doesn't quite
* work, since global keybindings won't be activated ("this
@@ -2021,7 +2031,7 @@ process_overlay_key (MetaDisplay *display,
{
MetaKeyBinding *binding;
keys->overlay_key_only_pressed = FALSE;
*modifier_press_only = FALSE;
/* We want to unfreeze events, but keep the grab so that if the user
* starts typing into the overlay we get all the keys */
@@ -2030,11 +2040,11 @@ process_overlay_key (MetaDisplay *display,
clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time);
binding = get_keybinding (keys, &keys->overlay_resolved_key_combo);
binding = get_keybinding (keys, resolved_key_combo);
if (binding &&
meta_compositor_filter_keybinding (display->compositor, binding))
return TRUE;
meta_display_overlay_key_activate (display);
trigger_callback (display, NULL);
}
else
{
@@ -2044,7 +2054,7 @@ process_overlay_key (MetaDisplay *display,
* while the key is still down
* - passive grabs are only activated on KeyPress and not KeyRelease.
*
* In this case, keys->overlay_key_only_pressed might be wrong.
* In this case, modifier_press_only might be wrong.
* Mutter still ought to acknowledge events, otherwise the X server
* will not send the next events.
*
@@ -2059,12 +2069,12 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
}
else if (event->type == CLUTTER_KEY_PRESS &&
resolved_key_combo_has_keycode (&keys->overlay_resolved_key_combo,
resolved_key_combo_has_keycode (resolved_key_combo,
event->hardware_keycode))
{
keys->overlay_key_only_pressed = TRUE;
*modifier_press_only = TRUE;
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
* on the next event if it's not the release of the overlay key */
* on the next event if it's not the release of the modifier key */
if (xdisplay)
XIAllowEvents (xdisplay,
clutter_input_device_get_device_id (event->device),
@@ -2076,6 +2086,43 @@ process_overlay_key (MetaDisplay *display,
return FALSE;
}
static gboolean
process_overlay_key (MetaDisplay *display,
ClutterKeyEvent *event,
MetaWindow *window)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
return process_special_modifier_key (display,
event,
window,
&keys->overlay_key_only_pressed,
&keys->overlay_resolved_key_combo,
(GFunc) meta_display_overlay_key_activate);
}
static void
handle_locate_pointer (MetaDisplay *display)
{
meta_compositor_locate_pointer (display->compositor);
}
static gboolean
process_locate_pointer_key (MetaDisplay *display,
ClutterKeyEvent *event,
MetaWindow *window)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
return process_special_modifier_key (display,
event,
window,
&keys->locate_pointer_key_only_pressed,
&keys->locate_pointer_resolved_key_combo,
(GFunc) handle_locate_pointer);
}
static gboolean
process_iso_next_group (MetaDisplay *display,
ClutterKeyEvent *event)
@@ -2129,6 +2176,10 @@ process_key_event (MetaDisplay *display,
if (handled)
return TRUE;
handled = process_locate_pointer_key (display, event, window);
if (handled) /* Continue with the event even if handled */
return FALSE;
handled = process_iso_next_group (display, event);
if (handled)
return TRUE;
@@ -2217,6 +2268,7 @@ meta_keybindings_process_event (MetaDisplay *display,
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_END:
keys->overlay_key_only_pressed = FALSE;
keys->locate_pointer_key_only_pressed = FALSE;
return FALSE;
case CLUTTER_KEY_PRESS:
@@ -4403,20 +4455,26 @@ meta_display_init_keys (MetaDisplay *display)
handler->name = g_strdup ("overlay-key");
handler->flags = META_KEY_BINDING_BUILTIN;
g_hash_table_insert (key_handlers, g_strdup ("overlay-key"), handler);
g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("locate-pointer-key");
handler->flags = META_KEY_BINDING_BUILTIN;
g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("iso-next-group");
handler->flags = META_KEY_BINDING_BUILTIN;
g_hash_table_insert (key_handlers, g_strdup ("iso-next-group"), handler);
g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("external-grab");
handler->func = handle_external_grab;
handler->default_func = handle_external_grab;
g_hash_table_insert (key_handlers, g_strdup ("external-grab"), handler);
g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
external_grabs = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL,

View File

@@ -81,6 +81,7 @@ static gboolean use_system_font = FALSE;
static PangoFontDescription *titlebar_font = NULL;
static MetaVirtualModifier mouse_button_mods = Mod1Mask;
static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
static MetaKeyCombo locate_pointer_key_combo = { 0, 0, 0 };
static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
static gboolean raise_on_click = TRUE;
@@ -145,6 +146,7 @@ static gboolean titlebar_handler (GVariant*, gpointer*, gpointer);
static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer);
static gboolean locate_pointer_key_handler (GVariant*, gpointer*, gpointer);
static gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer);
static void init_bindings (void);
@@ -427,6 +429,14 @@ static MetaStringPreference preferences_string[] =
overlay_key_handler,
NULL,
},
{
{ "locate-pointer-key",
SCHEMA_MUTTER,
META_PREF_KEYBINDINGS,
},
locate_pointer_key_handler,
NULL,
},
{ { NULL, 0, 0 }, NULL },
};
@@ -1475,6 +1485,36 @@ overlay_key_handler (GVariant *value,
return TRUE;
}
static gboolean
locate_pointer_key_handler (GVariant *value,
gpointer *result,
gpointer data)
{
MetaKeyCombo combo;
const gchar *string_value;
*result = NULL; /* ignored */
string_value = g_variant_get_string (value, NULL);
if (!string_value || !meta_parse_accelerator (string_value, &combo))
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse value for locate-pointer-key\n");
return FALSE;
}
combo.modifiers = 0;
if (locate_pointer_key_combo.keysym != combo.keysym ||
locate_pointer_key_combo.keycode != combo.keycode)
{
locate_pointer_key_combo = combo;
queue_changed (META_PREF_KEYBINDINGS);
}
return TRUE;
}
static gboolean
iso_next_group_handler (GVariant *value,
gpointer *result,
@@ -1688,7 +1728,15 @@ init_bindings (void)
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
pref->builtin = 1;
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
g_hash_table_insert (key_bindings, g_strdup (pref->name), pref);
pref = g_new0 (MetaKeyPref, 1);
pref->name = g_strdup ("locate-pointer-key");
pref->action = META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
pref->combos = g_slist_prepend (pref->combos, &locate_pointer_key_combo);
pref->builtin = 1;
g_hash_table_insert (key_bindings, g_strdup (pref->name), pref);
}
static gboolean
@@ -1966,6 +2014,12 @@ meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
*combo = overlay_key_combo;
}
void
meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo)
{
*combo = locate_pointer_key_combo;
}
const char *
meta_prefs_get_iso_next_group_option (void)
{

View File

@@ -3679,6 +3679,13 @@ meta_window_activate_full (MetaWindow *window,
{
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
gboolean allow_workspace_switch;
if (window->unmanaging)
{
g_warning ("Trying to activate unmanaged window '%s'", window->desc);
return;
}
meta_topic (META_DEBUG_FOCUS,
"_NET_ACTIVE_WINDOW message sent for %s at time %u "
"by client type %u.\n",

View File

@@ -625,6 +625,23 @@ dbus_idle_monitor_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor',
)
mutter_built_sources += dbus_idle_monitor_built_sources
if have_profiler
mutter_sources += [
'backends/meta-profiler.c',
'backends/meta-profiler.h',
]
dbus_interfaces_dir = join_paths(datadir, 'dbus-1', 'interfaces')
sysprof3_dbus_file = join_paths(dbus_interfaces_dir, 'org.gnome.Sysprof3.Profiler.xml')
dbus_sysprof3_profiler_built_sources = gnome.gdbus_codegen('meta-dbus-sysprof3-profiler',
sysprof3_dbus_file,
interface_prefix: 'org.gnome.',
namespace: 'MetaDBus',
)
mutter_built_sources += dbus_sysprof3_profiler_built_sources
endif
if have_native_backend
cvt = find_program('cvt')

View File

@@ -239,6 +239,16 @@ struct _MetaPluginClass
*/
MetaInhibitShortcutsDialog * (* create_inhibit_shortcuts_dialog) (MetaPlugin *plugin,
MetaWindow *window);
/**
* MetaPluginClass::locate_pointer:
*
* Virtual function called when the user triggered the "locate-pointer"
* mechanism.
* The common way to implement this function is to show some animation
* on screen to draw user attention on the pointer location.
*/
void (*locate_pointer) (MetaPlugin *plugin);
};
/**

View File

@@ -322,6 +322,7 @@ int meta_prefs_get_drag_threshold (void);
* @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME
* @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME
* @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME
* @META_KEYBINDING_ACTION_LOCATE_POINTER_KEY: FILLME
* @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME
* @META_KEYBINDING_ACTION_LAST: FILLME
*/
@@ -419,6 +420,7 @@ typedef enum _MetaKeyBindingAction
META_KEYBINDING_ACTION_MOVE_TO_SIDE_W,
META_KEYBINDING_ACTION_MOVE_TO_CENTER,
META_KEYBINDING_ACTION_OVERLAY_KEY,
META_KEYBINDING_ACTION_LOCATE_POINTER_KEY,
META_KEYBINDING_ACTION_ISO_NEXT_GROUP,
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
META_KEYBINDING_ACTION_SWITCH_MONITOR,

View File

@@ -29,10 +29,9 @@ The tests are installed according to:
https://wiki.gnome.org/Initiatives/GnomeGoals/InstalledTests
if --enable-installed-tests is passed to configure. You can run them
uninstalled with:
if -Dtests=true is passed to `meson configure`. You can run them uninstalled with:
cd src && make run-tests
ninja test
Command reference
=================

View File

@@ -170,8 +170,9 @@ meta_wayland_cursor_surface_commit (MetaWaylandSurfaceRole *surface_role,
wl_list_init (&pending->frame_callback_list);
if (pending->newly_attached &&
(!cairo_region_is_empty (pending->surface_damage) ||
!cairo_region_is_empty (pending->buffer_damage)))
((!cairo_region_is_empty (pending->surface_damage) ||
!cairo_region_is_empty (pending->buffer_damage)) ||
!priv->buffer))
update_cursor_sprite_texture (META_WAYLAND_CURSOR_SURFACE (surface_role));
}
@@ -188,6 +189,9 @@ meta_wayland_cursor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *role,
ClutterPoint point;
ClutterRect logical_monitor_rect;
if (!priv->cursor_renderer)
return FALSE;
logical_monitor_rect =
meta_rectangle_to_clutter_rect (&logical_monitor->rect);

View File

@@ -95,6 +95,9 @@ G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND);
static void unset_selection_source (MetaWaylandDataDevice *data_device,
MetaSelectionType selection_type);
static MetaWaylandDataSource *
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
static MetaWaylandDataSource *
@@ -567,12 +570,14 @@ destroy_data_offer (struct wl_resource *resource)
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
{
if (seat && seat->data_device.dnd_data_source == offer->source &&
if (seat->data_device.dnd_data_source == offer->source &&
wl_resource_get_version (offer->resource) <
WL_DATA_OFFER_ACTION_SINCE_VERSION)
meta_wayland_data_source_notify_finish (offer->source);
else
{
if (seat->data_device.dnd_data_source == offer->source)
unset_selection_source (&seat->data_device, META_SELECTION_DND);
meta_wayland_data_source_cancel (offer->source);
meta_wayland_data_source_set_current_offer (offer->source, NULL);
}
@@ -1038,7 +1043,6 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
{
/* Detach the data source from the grab, it's meant to live longer */
meta_wayland_drag_grab_set_source (drag_grab, NULL);
meta_wayland_data_source_set_seat (source, NULL);
meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus);
meta_wayland_data_source_notify_drop_performed (source);

View File

@@ -43,6 +43,10 @@
#include "linux-dmabuf-unstable-v1-server-protocol.h"
#ifndef DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
#endif
#define META_WAYLAND_DMA_BUF_MAX_FDS 4
struct _MetaWaylandDmaBufBuffer
@@ -80,15 +84,28 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
if (buffer->dma_buf.texture)
return TRUE;
/*
* NOTE: The cogl_format here is only used for texture color channel
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
* for accessing the buffer memory. EGL will access the buffer
* memory according to the DRM fourcc code. Cogl will not mmap
* and access the buffer memory at all.
*/
if (!cogl_pixel_format_from_drm_format (dma_buf->drm_format, &cogl_format, NULL))
switch (dma_buf->drm_format)
{
/*
* NOTE: The cogl_format here is only used for texture color channel
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
* for accessing the buffer memory. EGL will access the buffer
* memory according to the DRM fourcc code. Cogl will not mmap
* and access the buffer memory at all.
*/
case DRM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
break;
case DRM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case DRM_FORMAT_ARGB2101010:
cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
break;
case DRM_FORMAT_RGB565:
cogl_format = COGL_PIXEL_FORMAT_RGB_565;
break;
default:
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Unsupported buffer format %d", dma_buf->drm_format);

View File

@@ -172,13 +172,16 @@ gtk_surface_request_focus (struct wl_client *client,
if (sequence)
{
uint32_t timestamp;
uint32_t timestamp, workspace_idx;
workspace_idx = meta_startup_sequence_get_workspace (sequence);
timestamp = meta_startup_sequence_get_timestamp (sequence);
meta_startup_sequence_complete (sequence);
meta_startup_notification_remove_sequence (display->startup_notification,
sequence);
if (workspace_idx >= 0)
meta_window_change_workspace_by_index (window, workspace_idx, TRUE);
meta_window_activate_full (window, timestamp,
META_CLIENT_TYPE_APPLICATION, NULL);

View File

@@ -737,6 +737,10 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
g_clear_pointer (&snippet, cogl_object_unref);
}
}
else
{
cogl_clear_object (&surface->texture);
}
/* If the newly attached buffer is going to be accessed directly without
* making a copy, such as an EGL buffer, mark it as in-use don't release

View File

@@ -115,13 +115,24 @@ meta_wayland_tablet_tool_set_cursor_surface (MetaWaylandTabletTool *tool,
return;
if (tool->cursor_surface)
wl_list_remove (&tool->cursor_surface_destroy_listener.link);
{
MetaWaylandCursorSurface *cursor_surface;
cursor_surface = META_WAYLAND_CURSOR_SURFACE (tool->cursor_surface->role);
meta_wayland_cursor_surface_set_renderer (cursor_surface, NULL);
meta_wayland_surface_update_outputs (tool->cursor_surface);
wl_list_remove (&tool->cursor_surface_destroy_listener.link);
}
tool->cursor_surface = surface;
if (tool->cursor_surface)
wl_resource_add_destroy_listener (tool->cursor_surface->resource,
&tool->cursor_surface_destroy_listener);
{
meta_wayland_surface_update_outputs (tool->cursor_surface);
wl_resource_add_destroy_listener (tool->cursor_surface->resource,
&tool->cursor_surface_destroy_listener);
}
meta_wayland_tablet_tool_update_cursor_surface (tool);
}

View File

@@ -193,8 +193,6 @@ meta_xwayland_grab_is_granted (MetaWindow *window)
backend = meta_get_backend ();
settings = meta_backend_get_settings (backend);
if (!meta_settings_are_xwayland_grabs_allowed (settings))
return FALSE;
/* Check whether the window is blacklisted */
meta_settings_get_xwayland_grab_patterns (settings, &whitelist, &blacklist);
@@ -214,6 +212,22 @@ meta_xwayland_grab_is_granted (MetaWindow *window)
return FALSE;
}
static gboolean
meta_xwayland_grab_should_lock_focus (MetaWindow *window)
{
MetaBackend *backend;
MetaSettings *settings;
/* Lock focus applies to O-R windows which never receive keyboard focus otherwise */
if (!window->override_redirect)
return FALSE;
backend = meta_get_backend ();
settings = meta_backend_get_settings (backend);
return meta_settings_are_xwayland_grabs_allowed (settings);
}
static void
meta_xwayland_keyboard_grab_activate (MetaXwaylandKeyboardActiveGrab *active_grab)
{
@@ -225,8 +239,8 @@ meta_xwayland_keyboard_grab_activate (MetaXwaylandKeyboardActiveGrab *active_gra
{
meta_verbose ("XWayland window %s has a grab granted", window->desc);
meta_wayland_surface_inhibit_shortcuts (surface, seat);
/* Use a grab for O-R windows which never receive keyboard focus otherwise */
if (window->override_redirect)
if (meta_xwayland_grab_should_lock_focus (window))
meta_wayland_keyboard_start_grab (seat->keyboard, &active_grab->keyboard_grab);
}
if (active_grab->window_associate_handler)

View File

@@ -99,7 +99,6 @@ static void
meta_x11_display_unmanage_windows (MetaX11Display *x11_display)
{
GList *windows, *l;
MetaWindow *window;
if (!x11_display->xids)
return;
@@ -109,9 +108,17 @@ meta_x11_display_unmanage_windows (MetaX11Display *x11_display)
for (l = windows; l; l = l->next)
{
window = l->data;
if (!window->unmanaging)
meta_window_unmanage (window, META_CURRENT_TIME);
if (META_IS_WINDOW (l->data))
{
MetaWindow *window = l->data;
if (!window->unmanaging)
meta_window_unmanage (window, META_CURRENT_TIME);
}
else if (META_IS_BARRIER (l->data))
meta_barrier_destroy (META_BARRIER (l->data));
else
g_assert_not_reached ();
}
g_list_free_full (windows, g_object_unref);
}