Compare commits

...

480 Commits

Author SHA1 Message Date
27bec68c67 wayland: Add support for show_window_menu 2014-03-14 10:22:13 -04:00
8ce4407a9f x11: Add support for a new _GTK_SHOW_WINDOW_MENU request
To show the window menu from a client-side decoration.
2014-03-14 10:22:13 -04:00
cebb6b2779 window: Remove unused and unnecessary parameters from meta_window_window_menu 2014-03-14 10:22:11 -04:00
d7771a30ee Convert window menus to a compositor implementation 2014-03-13 19:36:33 -04:00
10fb5e527f window: Export a bunch of state flags as accessor methods
This is necessary to reimplement window menus in gnome-shell.
2014-03-13 19:33:28 -04:00
7116786ad3 Add a META_MAXIMIZE_BOTH
Which has the value of META_MAXIMIZE_VERTICAL |
META_MAXIMIZE_HORIZONTAL.

This is an obvious code cleanup.
2014-03-13 18:33:17 -04:00
d294fa45d1 wayland: Add support for set_surface_type 2014-03-13 17:14:28 -04:00
e278d65f05 constraints 2014-03-13 17:14:28 -04:00
42408c1c38 hack to get things working for demo
have to figure out something better to put here
2014-03-13 17:14:28 -04:00
9ac086a613 Replace mutter-launch with logind integration
This uses David Herrmann's new logind sessions interface to retrieve
fds for input devices, rather than using a custom setuid helper to do
the management. This vastly simplifies the interface.

This requires systemd v210, at least.

https://bugzilla.gnome.org/show_bug.cgi?id=724604
2014-03-13 17:14:28 -04:00
de06346766 meta-weston-launch: Pause Clutter during VT switches 2014-03-13 17:14:28 -04:00
c22d6ad69c meta-weston-launch: Remove the "VT-switched lock"
We'll replace it by pausing the Clutter master clock.
2014-03-13 17:14:28 -04:00
64be6cf4f0 weston-launch: Pass the DRM device to Cogl
Open the device from weston-launch, and pass it to Cogl/Clutter.
This is a preliminary cleanup for our login1 integration.
2014-03-13 17:14:28 -04:00
a9d8107c3d window: Replace meta_window_type_changed with meta_window_set_type
Which does the equality checking for us.
2014-03-13 17:14:28 -04:00
a5d2c51392 window: Move recalc_type to window-x11.c
It's only used by the X11 codepath.
2014-03-13 17:14:28 -04:00
d1ea17e6a4 meta-weston-launch: Adapt to Clutter's new evdev open callback 2014-03-13 12:47:11 -04:00
b37ad66e9d xdg-shell: Update for new state change mechanism
We're still not properly going through the request system. This
will require a dense investigation of the code, but it will happen
soon...
2014-03-12 23:42:55 -04:00
c1f15348a5 Revert "weston-launch: Pass the DRM device to Cogl"
This reverts commit 857561baed.

This broke the build, and was pushed prematurely.
2014-03-12 14:48:46 -04:00
857561baed weston-launch: Pass the DRM device to Cogl
Open the device from weston-launch, and pass it to Cogl/Clutter.
This is a preliminary cleanup for our login1 integration.
2014-03-11 18:01:21 -04:00
a44cc9ef47 wayland: Fix build 2014-03-11 18:01:17 -04:00
d47b7ba038 Add meta_activate_session
This will be used on startup to switch to the newly activated session.
2014-03-11 17:25:40 -04:00
f21312e2fd meta-weston-launch: Redraw and update the cursor when switching back 2014-03-11 17:25:40 -04:00
394af33607 weston-launch: Allow activating our own VT by passing a negative value
This will be used to implement activate_session.
2014-03-11 17:25:40 -04:00
7314cdac94 weston-launch: Always use sd_session_get_vt 2014-03-11 17:25:40 -04:00
81025e37ea weston-launch: Stat the path before opening it 2014-03-11 17:25:39 -04:00
1bb9f1e333 weston-launch: Remove unused prototypes 2014-03-11 17:25:39 -04:00
b11c75c1c9 weston-launch: Rearrange code slightly
We need to initialize the main loops before our callback is called, so
this makes it make a slight bit of more sense.
2014-03-11 17:25:39 -04:00
757b626aee wayland: Add a few comments, rename some strings 2014-03-11 17:25:02 -04:00
fb3df5243f main: Add a --display-server option
This is an explicit option to launch mutter as a display server,
rather than relying on weston-launch.
2014-03-11 16:33:42 -04:00
e34792d9f0 wayland: Remove needless indirection 2014-03-11 16:00:43 -04:00
f397c32192 wayland: Make set_selection private
It's unused outside of us.
2014-03-11 15:42:37 -04:00
f79314d7b5 wayland: Fix destroying data sources
The resource is not embedded in the source, it's separate. We need
to get the user data here to not crash.
2014-03-11 15:30:17 -04:00
55c61259d8 wayland: Use g_slice_new0
And fix a leak.
2014-03-11 15:30:17 -04:00
5298cf0a3a wayland: Pull in a fix for a FIXME from Weston 2014-03-11 15:30:17 -04:00
f1dc1a0cbc wayland: Fix drag grabs
We need to have the seat here. This makes weston-dnd not crash when
clicking on an item.
2014-03-11 15:30:16 -04:00
2cf80bc647 Fix identification of CSD windows when checking whether to force fullscreen
We try to exempt CSD windows from being forced fullscreen if they are
undecorated and the size of the screen; however, we also catch almost
all windows that *do* need to be forced fullscreen in this check, since
they also have decorations turned off.

Identify actual CSD windows by checking whether _GTK_FRAME_EXTENTS is set -
GTK+ will always set this on CSD windows even if they have no invisible
borders or shadows at the current time.

We explicitly turn off the legacy-fullscreen check for native wayland windows
so we don't start legacy-fullscreening them if the new
meta_window_is_client_decorated() is later made more accurate.

https://bugzilla.gnome.org/show_bug.cgi?id=723029
2014-03-11 13:02:19 -04:00
40c15f6e2a Fix meta_window_titlebar_is_onscreen() for titlebar-less windows
Make the code correspond to the comment - the titlebar can't be
offscreen if there's no titlebar.

https://bugzilla.gnome.org/show_bug.cgi?id=723580
2014-03-11 13:02:19 -04:00
a8849621c9 window: Always save the user_rect when resizing Wayland windows
The user_rect represents the unconstrainted window size, and lots
of code in mutter assumes it can resize to the user_rect at any
time. If we wait for an attach to ACK and save the user rect, we'll
see lots of flickering as code is resizing to the old user_rect
at any time.
2014-03-11 12:29:11 -04:00
49c0be11d6 display: Rework event spewing
Make it a compile-time flag rather than a run-time flag, because
practically any time you're going to be debugging event spewing,
you're going to have to recompile anyway. Remove the WITH_VERBOSE_MODE
checks, too.
2014-03-11 10:24:13 -04:00
9df8e831be xwayland: Make sure to clear an existing surface if we have one
This fixes an assert fail when redecorating an X11 client.
2014-03-11 10:24:13 -04:00
84c6b2a3fa wayland: Remove an extra reset
We already reset the double-buffered state when we commit it, so this
is just superfluous.
2014-03-11 10:24:13 -04:00
06cd669ccb wayland: Fix bad copy-paste error in unset_fullscreen
This was causing memory corruption and a bad crasher with simple-egl.
2014-03-10 16:45:05 -04:00
81eb7d9537 Add META_GRAB_OP_WAYLAND_CLIENT
Which is used for Wayland popup grabs.

The issue here is that we don't want the code that raises or focuses
windows based on mouse ops to run while a client has a grab.

We still keep the "old" grab infrastructure in place for now, but
ideally we'd replace it eventually with a better grab-op infrastructure.
2014-03-10 15:11:03 -04:00
dd8d8e436d wayland: Remove special code for modal grabs
Since we never pass any Clutter events to Wayland, it's not needed.
2014-03-10 15:10:44 -04:00
d6b6b363ad seat: Add support for smooth scrolling 2014-03-10 11:36:36 -04:00
254e2e993c seat: Redo scroll handling
To make way for smooth scrolling
2014-03-10 11:36:36 -04:00
c595a9c29f seat: Reduce indentation 2014-03-10 11:36:36 -04:00
dfc7f7222b wayland-keyboard: Remove unused modifier indexes
This was copied from weston where they're used for compositor
keybindings. Mutter has its own keybindings code which doesn't need
this.

https://bugzilla.gnome.org/show_bug.cgi?id=722847
2014-03-07 15:00:04 +01:00
ef278eb547 meta-cursor-tracker: Initialize our position from MetaWaylandPointer's
Clutter's input device initial position defaults to (-1, -1) on most
backends but for the evdev backend we changed it to be inside the
stage to prevent the pointer from wandering outside the stage until it
first enters, after which our constraining callback won't let it go
out.

This makes us be in sync with the real position from the start.
2014-03-07 14:54:51 +01:00
38e26e5cc3 keybindings: Plug a GSettings instance leak 2014-03-06 19:22:39 +01:00
9773a879c3 cursor-tracker: Include gdk/gdkx.h
Needed for the call to gdk_x11_device_manager_lookup() introduced in
abd2abcde6 .
2014-03-06 19:22:39 +01:00
abd2abcde6 cursor-tracker: Avoid unnecessary round trip 2014-03-06 17:31:08 +01:00
a8f4651c72 MetaCursorTracker: fix uninitialized screen variable
We must call gdk_device_get_pointer() unconditionally, because
that sets the GdkScreen argument we use to obtain the root window.
2014-03-06 17:27:11 +01:00
54df7934ea Bump version to 3.11.91
Update NEWS.
2014-03-05 23:48:33 +01:00
9052efb0d9 build: Use non-deprecated feature test macros
_SVID_SOURCE has been deprecated in newer versions of glibc breaking
-WError; the recommended replacement of _DEFAULT_SOURCE is fairly
new, so switch to _XOPEN_SOURCE instead.
2014-03-05 23:48:33 +01:00
b346f98eb0 Fix positioning error for manually positioned windows
The "original coordinates" passed into meta_window_place() were the
coordinates of the client rectangle not the frame rectangle. When
meta_window_place() didn't place because the window was manually
positioned (e.g., 'xterm -geometry +x+y') that resulted in a window
being offset by the frame dimensions.

https://bugzilla.gnome.org/show_bug.cgi?id=724049
2014-03-05 17:22:56 -05:00
365af53797 Fix handling of dynamic updates to colors/font/etc.
Since the introduction of frame sync in GTK+, updates to titlebar font and
colors haven't been working because GTK+ counts on the frame clock to
do style updates, and the frame clock doesn't run for an unmapped
GdkWindow. (It's possible that GtkStyleContext changes subsequent to
the introduction of the frame clock were also needed to fully break
things.)

We actually need to map the MetaFrames GdkWindow and let the
compositor code send out the frame sync messages in order to pick up
style changes.

Hopefully no bad side effects will occur from this - we make the window
override-redirect, 1x1, and outside the bounds of the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=725751
2014-03-05 17:22:48 -05:00
bee59ec0e1 Use MetaCursorTracker to query the pointer position
Functionally equivalent in the X11 case, but also correct for
Wayland (where the X server doesn't have the updated pointer
position).

https://bugzilla.gnome.org/show_bug.cgi?id=725525
2014-03-05 23:09:48 +01:00
91384a32b4 keybindings: Fix ungrabs possibly failing after switching keymaps
We need to resolve the keycode from the keysym again since the keycode
might have changed if there was a keymap switch between the grab and
the ungrab.
2014-03-04 21:13:15 +01:00
72bd5fb814 keybindings: Fix external grabs not being ungrabbed
Before starting to use display_get_keybinding() we could compare
MetaKeyBinding.modifiers with MetaKeyCombo.modifiers directly. Now, we
need to resolve the virtual modifiers to match with the mask.
2014-03-04 21:13:13 +01:00
46af3ef9f6 keybindings: Keep keybindings in an hash table instead of an array
This allows us to look for a match with an O(1) search instead of O(n)
which is nice, particularly when running as a wayland compositor in
which case we have to do this search for every key press event (as
opposed to only when our passive grab triggers in the X compositor
case).

We actually need two hash tables. On one we keep all the keybindings
themselves which allows us to add external grabs without constantly
re-allocating the array we were using previously.

The other hash table is an index of the keybindings in the first table
by their keycodes and mask which is how we actually match the key
press events. This second table thus needs to be rebuilt when the
keymap changes since keycodes have to be resolved then but since we're
only keeping pointers to the first table it's a fast operation.

https://bugzilla.gnome.org/show_bug.cgi?id=725588
2014-03-04 15:53:36 +01:00
d417c615d5 keybindings: Use display_get_keybinding() instead of looping explicitly
Instead of looping over an array of keybindings to find the correct
binding, just use display_get_keybinding().

In the next commit, we'll change the array to be a hash map, so this
helps the patch be cleaner.

https://bugzilla.gnome.org/show_bug.cgi?id=725588
2014-03-04 15:51:17 +01:00
46cbd0bf48 keybindings: Rename MetaKeyPref.bindings to MetaKeyPref.combos
Let's call it what it really is, otherwise it's just confusing since
MetaKeyBinding also exists.

https://bugzilla.gnome.org/show_bug.cgi?id=725588
2014-03-04 15:46:06 +01:00
f3b6fead4d keybindings: Make MetaKeyPref, MetaKeyCombo and MetaKeyHandler private
There's no need for these to be public and keeping them all together
in the same header makes it easier when reading the code.

https://bugzilla.gnome.org/show_bug.cgi?id=725588
2014-03-04 15:46:00 +01:00
80de8ec643 monitor-kms: Fix copy-paste error with DPMS mode enum 2014-03-03 18:44:10 -05:00
4f7e2a9f3f MetaScreen: include _GTK_FRAME_EXTENTS in _NET_SUPPORTED
This enables CSD for X11 clients (in XWayland and in X11)
2014-03-02 23:16:50 +01:00
701e06d55d keybindings: Make move-to-monitor-* bindings known to g-c-c
Commit 0fe5c4f957 implemented new keybindings to move windows
between monitors, but did not add it to the appropriate keybinding
file.

https://bugzilla.gnome.org/show_bug.cgi?id=725338
2014-02-28 20:11:59 +01:00
94f39a493f window-actor: Guard against %NULL frame mask
Creating a new cogl texture may fail, in which case the intent to
free it will crash. While something is clearly wrong (insanely
large window, oom, ...), crashing the WM is harsh and we should
try to avoid it if at all possible, so carry on.

https://bugzilla.gnome.org/show_bug.cgi?id=722266
2014-02-28 20:11:58 +01:00
ddc171220a wayland: Remove destroy listener
Do to a bad mixup, the surface listener was never actually fired.
This was accidentally fixed as part of a refactoring in a27fb19,
but the surface listener was broken, and we started crashing. To
fix, just remove the surface listener, as we've mostly been testing
without it.
2014-02-28 13:20:42 -05:00
0313b38dd6 wayland: Don't try to disconnect the listener from the signal handler
This is not needed since the instance is being destroyed and in fact
actively harmful when code called from other handlers disconnects us
for other reasons. In that case we might crash because the
disconnection doesn't prevent other handlers from running in the
current signal emission and thus we try to remove ourselves from an
empty list.
2014-02-28 13:20:42 -05:00
d41fba6558 meta-shaped-texture: Check if the parent has mapped clones as well
When the  WindowActor has mapped clones we should ignore
the unobscured region as well, so we need to walk up and check it
as well.

https://bugzilla.gnome.org/show_bug.cgi?id=725180
2014-02-28 18:27:37 +01:00
770b58b367 wayland: Move "public" Wayland API to another header file 2014-02-28 10:24:06 -05:00
77838c2ca3 wayland: Do a giant code cleanup
This changes the user data of all surface extensions resources to be
the MetaWaylandSurface instead of the MetaWaylandSurfaceExtension,
which means that we no longer need all these pesky wl_container_ofs
in implementations.
2014-02-28 09:07:33 -05:00
e56cbfbd0f wayland: Rearrange create_surface_extension a tiny bit
This moves all the "uninteresting" variables we pass to the end.
2014-02-28 09:07:33 -05:00
a27fb19473 wayland: Do a small code cleanup
Pass the surface rather than the resource / client. This will become
a lot more helpful in the next commit.
2014-02-28 09:07:33 -05:00
674bcef6da Handle mouse-button-modifier being disabled
In case 'mouse-button-modifier' is disabled the mask is 0 which means
we would always grab.
2014-02-28 14:55:14 +01:00
86c1c30245 wayland: Add back wl_shell support 2014-02-28 08:32:14 -05:00
283546b379 wayland: Enable destroy animations for regular windows
Don't set the surface actor to a new buffer if it's becoming unmapped.
This is also technically wrong since we'll send out the release event,
but oh well.

We should probably decouple MetaWaylandBuffer from the CoglTexture
at some point, so we can send out releases on-demand.
2014-02-27 23:48:00 -05:00
98e3e5e50f Partially revert 5c99eae8a9
We must extract the window from XIDeviceEvent, to be able
to apply our workaround to spoof the event in compositor.c
2014-02-27 23:49:56 +01:00
b6a0d4d368 Revert "mutter-wayland: Add XKB VT switching keysyms."
This reverts commit 7283fb320f.

Now that we match on keycodes, this isn't needed anymore.
2014-02-27 15:41:00 -05:00
28859c604f keybindings: Don't use the keysym to match keybindings
We don't want to match the keysym so that e.g. an accelerator
specified as "<Super>a" works if the current keymap has a keysym other
than 'a' for that keycode which means that the accelerator would
become inaccessible in a non-latin keymap.

This is inconvenient for users that often switch keyboard layouts, or
even have different layouts in different windows, since they expect
system-level keybindings to not be affected by the current layout.

https://bugzilla.gnome.org/show_bug.cgi?id=678001
2014-02-27 21:39:42 +01:00
9e51d98f4a Remove tabpopup and friends
These are unused in gnome-shell, and add complexity. Remove them.
2014-02-27 13:55:58 -05:00
268a4c92ba window: Fix meta_window_get_client_area_rect
The shaded logic here was backwards.
2014-02-27 10:33:10 -05:00
71367e14d5 build: Define CLUTTER_ENABLE_COMPOSITOR_API 2014-02-27 15:20:35 +01:00
5c99eae8a9 display: clean up event handling
The only events we handle as XIEvents are FocusIn/Out, Enter and
Leave.  Motion, ButtonPress/Release, KeyPress/Release are handled
through clutter instead.
Among other things, this means we don't need to fake motion compression
by peeking over gdk event queue...
2014-02-27 14:57:52 +01:00
89aa5df711 display: fix inverted check from 75184d4c55
I noticed it, Jasper noticed it, we agreed to change it, and then
I forgot to do it before pushing...
2014-02-27 14:45:10 +01:00
b9a5d710b7 compositor: always redirect passive button grabs to clutter
All WM events (passive button grabs and passive keyboard grabs)
are handled through clutter now, so we must make sure we spoof
them even if they happen on frames (because that's where we
grab on)
2014-02-27 14:37:48 +01:00
65dd54a4db compositor: don't spoof events when running as a wayland compositor
Weirdly, clutter stopped segfaulting when we call clutter_x11 methods
and the backend is not right, but this is correct anyway, and
probably fixes some BadDrawable errors in mutter-wayland on x11,
caused by mixing windows of the outer X and windows of Xwayland.
2014-02-27 14:28:46 +01:00
b00fa70d91 display: move more event handling to clutter
Mouse event handling was duplicated, resulting in weird interactions
if clutter was allowed to see certain events (for example under
wayland, where it gets all events). Because now clutter sees all
X events, even when running as an x11 compositor, we can handle
everything using the clutter variants.
At the same time, rewrite a little the passive button grab code,
to make it clear what is being matched on what and why.
2014-02-27 03:13:33 +01:00
360d423faa MetaSurfaceActor: add a generic hook to retrieve the MetaWindow
This way we can find the window for a ClutterEvent even when
running as an x11 compositor.
2014-02-27 03:13:33 +01:00
394b44a2c2 compositor: fix mouse interactions on frames
meta_ui_window_is_widget() returns FALSE for frame windows, so we
must filter those explicitly (by letting the event go to gtk
and from there to MetaFrames). Also, for proper gtk widgets
(window menus) we want to let gtk see all events, including
keyboard, otherwise we break keynav in the window menu.
This means that having a window menu open disables keybindings
(because the event doesn't run through clutter)
2014-02-27 03:13:32 +01:00
ed6821a819 keybindings: fix per window keybindings
We must spoof events to clutter even if they are associated
with a MetaWindow, because keyboard events are always associated
with one (the focus window), and we must process keybindings
for window togheter with the global ones if they include Super,
because we're not going to see them again.
2014-02-27 03:13:32 +01:00
23b0f7be43 display: Always use the key focused window for key events
We no longer grab the actor's key focus, so this is necessary.
2014-02-27 03:13:32 +01:00
7f195aec7a display: Don't grab the window actor's key focus
This breaks gnome-shell's actor tracking code.
2014-02-27 03:13:32 +01:00
da13e3d237 display: Return TRUE when we've handled an X event appropriately
We need to do this to make sure events aren't improperly sent
to Clutter in the next commit.
2014-02-27 03:13:32 +01:00
75184d4c55 display: Simplify checks to see if a window is the root window 2014-02-27 03:13:32 +01:00
eb75306f8a Revert "window-actor: Complete the removal of update_shape"
This reverts commit 640102c03b.
2014-02-26 20:52:44 -05:00
98c4b82907 Revert "window: Update the shape, input, and opaque regions immediately"
This reverts commit c0d791cd6e.
2014-02-26 20:45:38 -05:00
640102c03b window-actor: Complete the removal of update_shape
I accidentally stashed the rest of the stuff and forgot to
commit it... oops.
2014-02-26 20:04:19 -05:00
c0d791cd6e window: Update the shape, input, and opaque regions immediately
... and individually. It turns out that updating the opaque region
was causing the shape region to be updated, which was causing a new
shape mask to be generated and uploaded to the GPU. Considering
GTK+ regenerates the opaque region on pretty much any focus change,
this is not good.
2014-02-26 20:03:16 -05:00
41d5e69de5 window-actor: Kill off another use of MetaFrameBorders 2014-02-26 20:02:13 -05:00
2dc7371944 window-actor: Don't pass around client_area
To solve a performance regression, the three update_*_region
calls are going to be split up, so just call get_client_area_rect
in the methods itself.
2014-02-26 20:02:11 -05:00
ec2c3e1438 window: Add meta_window_get_client_area_rect 2014-02-26 19:54:41 -05:00
c5c3806a04 window-x11: Add back missing error trap
This was accidentally removed in 9f5087e.
2014-02-26 19:54:07 -05:00
ac0c7df4a3 keybindings: fix invalid read after a keybinding is removed
The handler pointer is dangling in MetaKeyBinding until
rebuild_key_binding_table() is run, so we can't dereference it.
Because we only need the flags at ungrab time, store a copy
in the MetaKeyBinding structure.

https://bugzilla.gnome.org/show_bug.cgi?id=724402
2014-02-26 15:20:06 +01:00
d85845426c window-actor: Fix culling
At some point meta_window_actor_cull_out stopped calling
meta_cullable_cull_out_children which caused the unobscured region
to never be set for the stex.

https://bugzilla.gnome.org/show_bug.cgi?id=725216
2014-02-26 15:01:07 +01:00
060e60f2a0 window: fix loading the window type initially
This code was lost in the window/window-x11 split.
2014-02-26 00:21:52 +01:00
26cf75d5a4 MetaWindowX11: fix listening for shape events
This code was lost when support for input shapes was originally
introduced.
2014-02-25 01:29:50 +01:00
9f5087e97d Fix input and bounding shapes
For decorated windows, we don't want to apply any input
shape, because the frame is always rectangular and eats
all the input.
The real check is in meta-window-actor, where we consider
if we need to apply the bounding shape and the input shape
(or the intersection of the two) to the surface-actor,
but as an optimization we avoid querying the server in
meta-window.
Additionally, for undecorated windows, the "has input shape"
check is wrong if the window has a bounding shape but not an
input shape.
2014-02-25 01:27:32 +01:00
45624f2edf MetaWindowActor: survive having no MetaSurfaceActor
We need a MetaWaylandSurface to build a MetaSurfaceActor, but
we don't have one until we get the set_window_xid() call from
XWayland. On the other hand, plugins expect to see the window
actor right from when the window is created, so we need this
empty state.

Based on a patch by Jasper St. Pierre.
2014-02-25 01:22:56 +01:00
153f843ea6 MetaSurfaceActor: move freeze accounting to MetaWindowActor
Turns out we only ever need to freeze/thaw whole windows, not
surfaces or subsurfaces.
This will allow removing the surface actor without losing
the count.
2014-02-25 01:20:22 +01:00
f0cd9b0687 wayland-surface: Rework construction / destruction yet again
This time, to make way for MetaSurfaceActorEmpty. This also fixes
destroy effects as a side effect. It still has issues if we try
to re-assign an actor that's already toplevel (e.g. somebody
re-popping up a menu that's already being destroyed), but this
will be fixed soon.

The idea here is that MetaWindowActor will do the unparenting of
the surface actor when it itself is destroyed. To prevent bad issues
with picking, we only make the surface actor reactive when it's
toplevel.
2014-02-24 14:46:19 -05:00
1783bf20ec Revert "window: Delay the showing of XWayland clients until set_window_id"
This reverts commit 59c8b949ad.
2014-02-24 14:46:19 -05:00
9b24ae2033 Revert "compositor: Delay meta_compositor_add_window until the first show"
This reverts commit 4efe4483fb.
2014-02-24 14:46:18 -05:00
0be4622e14 stack-tracker: Comment out bad warning
It triggers too often, making G_DEBUG=fatal-warnings quite useless.
Owen is going to rewrite this code sometime in the near future, so
I'm just gonna kill this warning for now.
2014-02-24 09:46:22 -05:00
bcd5446cdc core: prevent early MetaIdleMonitor destruction when its invoker vanishes
If the last reference of a MetaIdleMonitor is held by the caller, it may
happen that the last reference is lost when calling the GDestroyNotify,
if this happens when the watched DBus name vanishes, the object (and the
watches hashtable) are destroyed while manipulating the watches hashtable,
so bad things may happen then.

Fix this by wrapping the operation by a ref/unref pair, so the object would
be destroyed after operating on the hashtable.

https://bugzilla.gnome.org/show_bug.cgi?id=724969
2014-02-24 11:50:08 +01:00
04b5232960 compositor: The stage is always focused when we're a Wayland compositor
gnome-shell has some complex tracking to set the X input focus
correctly, assuming various things about how the stage is set up in X11.
For instance, it assumes that all actors that get key focus are
gnome-shell Chrome actors that will get events through the stage, so
when one of them is focused, it will try to set the focus back to the
stage.

In Wayland, windows are considered chrome actors that will get key
events through the stage, so this only has the result of unfocusing any
windows that have just received key focus.

We should probably move this input focus moving to mutter instead of
gnome-shell so we can better use mutter's internal state and heuristics.
2014-02-23 12:34:53 -05:00
f860df4b2d Revert "compositor: fix focusing the stage window"
This reverts commit 876f81db12.

This doesn't quite work properly, and is overcomplicated.
2014-02-23 12:34:52 -05:00
ff8c4b1bcf pointer/keyboard: Fix segfault once more
If the resource is destroyed before the surface, then we'll kill
ourselves. Why can I never seem to write these correctly...
2014-02-23 10:00:31 -05:00
337c69e223 pointer/keyboard: Unset focus_resource when the surface is destroyed
focus_resource is supposed to be set only if focus_surface is
as well.
2014-02-22 18:15:53 -05:00
14841475b5 meta-window-actor: Fix paint_volume
We cannot intersect the the complete volume with the unobscured bounds
because it does not include the shadows. So just intersect it with the
windows's shape bounds and union it with the shadow bounds.

This also matches what the comment in the code says:
"We could compute an full clip region as we do for the window texture,
but the shadow is relatively cheap to draw, and a little more complex to clip,
so we just catch the case where the shadow is completely obscured
and doesn't need to be drawn at all."
2014-02-21 20:39:25 +01:00
7283fb320f mutter-wayland: Add XKB VT switching keysyms.
It turns out XKB has keysyms for these for no real reason, and I
was hitting those instead of the <Primary><Alt>F1 path. This is
ridiculous, but key, so is the entirety of XKB.

This took an embarassingly long time to figure out and debug.
2014-02-21 13:50:40 -05:00
020cfa7283 surface-actor-x11: Recreate damage when the toplevel X window changes 2014-02-20 14:50:48 -05:00
83aca0b53d window-actor: Split into two subclasses of MetaSurfaceActor
The rendering logic before was somewhat complex. We had three independent
cases to take into account when doing rendering:

  * X11 compositor. In this case, we're a traditional X11 compositor,
    not a Wayland compositor. We use XCompositeNameWindowPixmap to get
    the backing pixmap for the window, and deal with the COMPOSITE
    extension messiness.

    In this case, meta_is_wayland_compositor() is FALSE.

  * Wayland clients. In this case, we're a Wayland compositor managing
    Wayland surfaces. The rendering for this is fairly straightforward,
    as Cogl handles most of the complexity with EGL and SHM buffers...
    Wayland clients give us the input and opaque regions through
    wl_surface.

    In this case, meta_is_wayland_compositor() is TRUE and
    priv->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND.

  * XWayland clients. In this case, we're a Wayland compositor, like
    above, and XWayland hands us Wayland surfaces. XWayland handles
    the COMPOSITE extension messiness for us, and hands us a buffer
    like any other Wayland client. We have to fetch the input and
    opaque regions from the X11 window ourselves.

    In this case, meta_is_wayland_compositor() is TRUE and
    priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11.

We now split the rendering logic into two subclasses, which are:

  * MetaSurfaceActorX11, which handles the X11 compositor case, in that
    it uses XCompositeNameWindowPixmap to get the backing pixmap, and
    deal with all the COMPOSITE extension messiness.

  * MetaSurfaceActorWayland, which handles the Wayland compositor case
    for both native Wayland clients and XWayland clients. XWayland handles
    COMPOSITE for us, and handles pushing a surface over through the
    xf86-video-wayland DDX.

Frame sync is still in MetaWindowActor, as it needs to work for both the
X11 compositor and XWayland client cases. When Wayland's video display
protocol lands, this will need to be significantly overhauled, as it would
have to work for any wl_surface, including subsurfaces, so we would need
surface-level discretion.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-20 14:44:31 -05:00
0b055fae2e window-actor: Kill off needs_pixmap
It's mostly equivalent to the case where we've already detached
the pixmap, *except* for the x11_size_changed case. We can simply
detach the pixmap at the time the window changes size, though.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-20 11:51:52 -05:00
bc79259398 window-actor: Don't queue a redraw when queueing a new pixmap
We guarantee ourselves that a valid pixmap will appear any time
that the window is painted. The window actor will be scheduled
for a repaint if it's added / removed from the scene graph, like
during construction, if the size changes, or if we receive damage,
which are the existing use cases where this function is called.

So, I can't see any reason that we queue a redraw in here.

With the split into surface actors, we don't have an easy place
we can use to queue a redraw, and since it's unnecessary, we can
just drop it on the floor.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-20 11:35:01 -05:00
7ebf5aa69a pointer/keyboard: Properly handle destruction
If the client destroys the pointer resource, we shouldn't unfocus the
surface, and we should regrab it when the client gets the pointer
resource again.

This also fixes a crash at surface destruction because of the unchecked
wl_link_remove that will happen on both pointer and surface destroy.
2014-02-20 11:35:01 -05:00
7499621ecb Bump version to 3.11.90
Update NEWS.
2014-02-19 21:58:42 +01:00
4de3f7ca29 Make tile preview a compositor plugin effect
https://bugzilla.gnome.org/show_bug.cgi?id=665758
2014-02-19 21:55:35 +01:00
17462c21e8 pointer/keyboard: fix setting focus
Set focus to NULL after using the variable
2014-02-19 10:24:36 -05:00
c964ef4e01 window-actor: Fix build
I'm bad.
2014-02-19 01:11:42 -05:00
0dccc440b6 window-actor: Kill off a nonsensical edge case
We can never have a window actor that represents either the X root
window or the stage window, so it doesn't make sense to bail out
early in case we do.

I'd imagine that this came from a much earlier version of the code
where the compositor was much separate and had its own MapNotify
handling.
2014-02-18 23:36:46 -05:00
48f7232492 pointer: Don't send modifiers on mouse enter
I talked to Kristian about this. It should be enough to simply
send it when we activate the surface and give it keyboard focus.
2014-02-18 23:21:06 -05:00
ff5867e4d3 pointer: Make the code here a bit clearer 2014-02-18 23:21:06 -05:00
a5d950f453 pointer/keyboard: Fix focus setting once again
Yet another large-scale restructuring... this is some messy code.
2014-02-18 23:21:06 -05:00
7615d17293 wayland: Tie activate / deactivate to appears-focused
... rather than actual focus. This makes things behave better.
2014-02-18 23:21:06 -05:00
374e30043b wayland: Remove width / height from MetaWaylandBuffer
They're in the texture.
2014-02-18 22:43:24 -05:00
f771bb88d6 Revert "wayland: Explicitly destroy the surface actor"
This reverts commit 283a81eac0.

This can't be done yet, as it will crash when we try to do a destroy
effect from a plugin. The surface actor needs to outlive the surface
in this case.

Though, the unparenting happening is wrong anyway for a destroy effect.
We need to figure out a sane way of doing this unparenting only after
all effects have finished.
2014-02-18 22:23:08 -05:00
7ef8d21e48 wayland: Allow destroying the wl_surface before the xdg_surface
As resource destruction can happen in any order at shutdown, we
need to be flexible here. A client disconnecting without cleaning
up all its resources should not assert fail.
2014-02-18 22:21:33 -05:00
c251eb8ec0 window-group: Don't special-case the unredirected window
Since the unredirected window MetaWindowActor is stacked on top, it
will naturally get culled out of the process, so we can remove the
special casing here. Unfortunately, with the way that the code is
currently structured, it's too difficult to actually prevent setting
the clip / visible regions if the window is redirected, so just let
those be set for unredirected windows for now.
2014-02-18 21:29:50 -05:00
1e6b3faa83 Fix the input region not working properly
The input region was set on the shaped texture, but the shaped texture
was never picked properly, as it was never set to be reactive. Move the
pick implementation and reactivity to the MetaSurfaceActor, and update
the code everywhere else to expect a MetaSurfaceActor.
2014-02-18 21:29:23 -05:00
e62fe956fd window: Enable pinging on Wayland windows
I implemented pinging, but never actually enabled the feature
properly on Wayland surfaces by setting the net_wm_ping hint to
TRUE, causing the fallback path to always be hit.

Rename net_wm_ping to can_ping so it doesn't take on an
implementation-specific meaning, and set it for all Wayland windows.
2014-02-18 20:30:52 -05:00
24c5290d7f main: Kill a runtime warning
g_setenv doesn't take NULL for a value.
2014-02-18 20:30:36 -05:00
00c8d3c897 xdg-shell: Update to latest renames for focused_set / focused_unset 2014-02-18 19:02:17 -05:00
cc13f8f65e wayland: Fix compile error
I tested this with meta_window_get_input_rect and decided to change
it at the last minute. Turns out meta_window_get_rect is unlike all
the others. Just access window->rect directly instead.
2014-02-18 19:01:50 -05:00
47f4c9db7b wayland-surface: Correct xdg_popup placement
Now that we call set_custom_frame_extents, the frame rect corresponds
to the "visible window geometry" used for constrainment, while the
x/y fields in get_xdg_popup instead are relative to the surface.
2014-02-18 18:55:54 -05:00
4c621cc30f pointer/keyboard: Make sure to clean up the destroy listeners when releasing 2014-02-18 18:39:19 -05:00
756a412436 pointer: Make nested grabs work
Something noticed on code inspection. If we have a popup grab,
it will always return FALSE. The code here clearly meant to continue
if we had an existing popup grab from an existing client.
2014-02-18 18:06:55 -05:00
be16c2fe71 pointer: Reindent 2014-02-18 18:06:17 -05:00
a364c2a96b pointer/keyboard: Make sure not to get stale on client resources as well
Both the pointer/keyboard resource and surface resource can be destroyed
at any point in the destruction process, so we need to have destroy
listeners on both. To make the code easier to follow, rename ->focus
to ->focus_surface at the same time, and rearrange the code so that
the two of them are always grouped together.
2014-02-18 18:03:31 -05:00
414259a7f8 wayland: Fix cast warning
It's sometimes hard to see around all the deprecation warnings. Sorry
about that...
2014-02-18 17:26:03 -05:00
283a81eac0 wayland: Explicitly destroy the surface actor
This shouldn't change anything right now, but it's better to be
careful than anything else. This is where the actor should be
destroyed.
2014-02-18 17:07:36 -05:00
2a145262c7 wayland: Rework how surface destruction works
To prevent the MetaSurfaceActor from being destroyed, we normally
unparent it before we unmanage the window. However, this doesn't
work for XWayland windows, which we unmanage when we get UnmapNotify
or DestroyNotify, not when we get the wl_surface_destroy.

To solve this, add an early hook in meta_window_unmanage that
unparents the surface actor if we have one. At the same time, clean
up the destruction code to remove old comments and assumptions about
how wl_shell behaves.
2014-02-18 17:01:33 -05:00
57728b4322 Kill HAVE_WAYLAND 2014-02-17 21:50:32 -05:00
ef24fb6296 wayland: Don't use WESTON_LAUNCHER_SOCK
We can simply check the windowing backend.
2014-02-17 21:50:32 -05:00
86f057a712 monitor: Add a Wayland backend
We shouldn't crash when trying to run nested under Wayland. Just
use the dummy backend for now until we are able to run with a
system compositor.
2014-02-17 21:50:32 -05:00
dcd628d289 wayland: Kill meta_wayland_compositor_is_native
It's unused. Squash the remaining functionality, setting the DRM FD,
into the main path.
2014-02-17 21:15:31 -05:00
6038877c4c cursor-tracker: Kill off the last user of is_native 2014-02-17 21:11:57 -05:00
4e6321c239 monitor: Kill off another use of is_native 2014-02-17 20:51:35 -05:00
304a525744 wayland: Remove is_native from seat
We can easily do this with a Clutter backend check instead...
2014-02-17 20:49:04 -05:00
f26de405dd main: Remove clutter / cogl option groups
Neither of these groups are too useful, and all the switches useful
for debugging can also be controlled by envvars.
2014-02-17 20:41:36 -05:00
ed18580118 default: Improve the destroy effect as well 2014-02-17 19:27:33 -05:00
b65649186d pointer/keyboard: Put the destroy listener on the right resource
We care about when the surface is destroyed, not when the wl_pointer
slash wl_keyboard resource is destroyed.
2014-02-17 19:22:30 -05:00
515dc08a97 pointer/keyboard: Do a series of renames to our listener as well 2014-02-17 19:22:30 -05:00
2e7a56a28f wayland: Rename resource_destroy_cb to wl_surface_destructor
So it doesn't seem like a wl_listener callback.
2014-02-17 19:22:30 -05:00
c485637a61 default: Don't use anchor points
It doesn't work now that we set the pivot point. This breaks the
maximize effect, but it fixes the destroy effect. The maximize effect
looks bad anyway, so it's not too important to me.
2014-02-17 17:57:45 -05:00
f9f2a82e18 xwayland: Don't -retro
This means we see black instead of checkerboard for now when resizing,
but that's better.
2014-02-17 17:57:40 -05:00
2f4563132a default: Use a consistent rand() for monitor backgrounds
g_random_int() is seeded with /dev/urandom, so it's not consistent.
2014-02-17 14:02:13 -05:00
e3a0f2c546 default: Don't wait to show the stage
We can show it immediately now...
2014-02-17 13:57:35 -05:00
d39baeb8ad wayland-surface: Destroy the right thing
data is the wl_client, which we don't want to destroy. Destroy
our XdgShell pointer instead.
2014-02-17 12:53:56 -05:00
f27f6aab78 Update to new xdg-shell pinging standards 2014-02-16 10:21:22 -05:00
a66060e21a Revert "Move window pings to MetaWindow"
This was a bad idea, as ping/pong has moved to a client-specific
request/event pair, rather than a surface-specific one. Revert
the changes we made here and correct the code to make up for it.

This reverts commit aa3643cdde.
2014-02-16 10:21:22 -05:00
11aa3c030b wayland-surface: Don't require we manually bump the version for xdg-shell
It's in the protocol as an enum.
2014-02-16 10:21:22 -05:00
bd1bec5617 wayland-surface: Prefix xdg-shell methods with "xdg_shell_" 2014-02-16 10:21:22 -05:00
d9659d4b36 wayland-surface: Don't crash when someone tries to run a native app using old gtk
This ends up calling set_dbus_properties with a NULL
window, instead of segfaulting the compositor return so that the broken
app dies instead.

https://bugzilla.gnome.org/show_bug.cgi?id=724472
2014-02-16 16:19:23 +01:00
d043d9943b idle-monitor: avoid XSyncBadAlarm X error
If we fail to find the IDLETIME counter, then the alarm variable will be
uninitialised.  Most code paths are careful to check this before
submitting XSync calls, but there is one check missing.

https://bugzilla.gnome.org/show_bug.cgi?id=724364
2014-02-15 13:14:01 +01:00
a0ef7c7142 Move position-changed / size-changed signals to the MetaWindow
They fit more appropriately over here...

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-14 23:44:39 -05:00
4efe4483fb compositor: Delay meta_compositor_add_window until the first show
In order for the compositor to properly determine whether a client
is an X11 client or not, we need to wait until XWayland calls
set_window_id to mark the surface as an XWayland client. To prevent
the compositor from getting tripped up over this, make sure that
the window has been fully initialized by the time we call
meta_compositor_add_window.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-14 23:44:38 -05:00
aec3edb1cc Always map the client and frame windows
Traditionally, WMs unmap windows when minimizing them, and map them
when restoring them or wanting to show them for other reasons, like
upon creation.

However, as metacity morphed into mutter, we optionally chose to keep
windows mapped for the lifetime of the window under the user option
"live-window-previews", which makes the code keep windows mapped so it
can show window preview for minimized windows in other places, like
Alt-Tab and Expose.

I removed this preference two years ago mechanically, by removing all
the if statements, but never went through and cleaned up the code so
that windows are simply mapped for the lifetime of the window -- the
"architecture" of the old code that maps and unmaps on show/hide was
still there.

Remove this now.

The one case we still need to be careful of is shaded windows, in which
we do still unmap the client window. In the future, we might want to
show previews of shaded windows in the overview and Alt-Tab. In that
we'd also keep shaded windows mapped, and could remove all unmap logic,
but we'd need a more complex method of showing the shaded titlebar, such
as using a different actor.

At the same time, simplify the compositor interface by removing
meta_compositor_window_[un]mapped API, and instead adding/removing the
window on-demand.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-14 23:19:41 -05:00
0c5a6ad775 window: don't set _NET_WM_FULLSCREEN_MONITORS to bogus values
Prior to the DisplayConfig merge, we would set _NET_WM_FULLSCREEN_MONITORS
to (unsigned)-1 when unset. After that, we would have invalid
reads inside meta_screen_monitor_index_to_xinerama_index() (called
with -1).
The way I read the specification, the proper way to indicate
that the window is back to fullscreen on all monitors is to
remove the property, so do that.

Also, add an assertion that meta_screne_monitor_index_to_xinerama_index()
is doing the right thing.

https://bugzilla.gnome.org/show_bug.cgi?id=724258
2014-02-13 13:16:51 +01:00
2be5401b1e window: fix invalid read in computing the input shape
If we are reported only one rectangle in the input shape, we should
not try to read more.

https://bugzilla.gnome.org/show_bug.cgi?id=724257
2014-02-13 13:13:35 +01:00
f16e9b2ee7 wayland-surface: Make set_margin double-buffered as well 2014-02-10 14:16:06 -05:00
06380938d4 wayland-surface: Make set_fullscreen / set_maximized and friends double-buffered 2014-02-09 18:23:39 -05:00
87b20d7f2a autogen.sh: use #!/bin/sh instead of #!/bin/bash
We don't have any bashisms in this file, so we may as well use sh.

https://bugzilla.gnome.org/show_bug.cgi?id=722530
2014-02-09 11:54:51 -05:00
593db0baee default: Make the map animation more friendly 2014-02-09 11:53:15 -05:00
6b66553493 display: Remove unused variable 2014-02-09 11:53:15 -05:00
ddaae9c923 Fix build
I broke it while cherry picking the last commit.
2014-02-09 16:39:04 +01:00
0c7a7d7527 Disable clutter's high dpi scaling
mutter needs some work to work with high dpi scaling so disable
the scaling until that is fixed.

https://bugzilla.gnome.org/show_bug.cgi?id=723931
2014-02-09 16:25:37 +01:00
6561b53346 display: Clean up screen management code 2014-02-07 19:52:34 -05:00
def5e86673 wayland: Add support for the set_margin request 2014-02-07 19:28:36 -05:00
0c213c8fee wayland: Add support for the delete event 2014-02-07 19:28:36 -05:00
912a0abd26 wayland: Remove edges
This is an upstream change to xdg-shell.
2014-02-07 19:28:36 -05:00
d694260ad2 xwayland: Fix xwayland
Don't give us a freed pointer here.
2014-02-07 19:28:05 -05:00
8566566451 xwayland: Split out the XWayland stuff into its own private struct 2014-02-07 16:21:27 -05:00
0ce64e46e8 build: Don't build client-protocols for things
We don't use these.
2014-02-07 16:21:27 -05:00
a8336669a3 shaped-texture: Fix unused variable warning
(cherry picked from commit 101a13c86d)
2014-02-05 22:51:46 +01:00
f6db756326 shaped-texture: Move unobscured_region processing here
We want to remove a bunch of auxilliary duties from the MetaWindowActor
and MetaSurfaceActor, including some details of how culling is done.
Move the unobscured region culling code to the MetaShapedTexture, which
helps the actor become "more independent".

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-05 14:42:38 -05:00
27ab516f41 cullable: Reset the culling state instead of skipping the traversal
When we traversed down to reset the culling state, previously we
would just skip any actors that wanted culling. In order to properly
reset the unobscured_region before painting, we need to traverse down
to these places as well. Do this by calling cull_out with NULL regions
for both arguments, and adapt existing cull_out implementations to
match.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-05 14:24:08 -05:00
9542b464bf window-actor: Clean up whitespace 2014-02-05 14:14:41 -05:00
1ebaaa1950 shaped-texture: Clean up code flow a bit
This is easier for me to read.
2014-02-05 14:10:50 -05:00
71efbf0330 shaped-texture: Constify clip
This matches upstream
2014-02-05 14:10:49 -05:00
a6539463be shaped-texture: Remove get_clip
It seems that this code is trying to transform from "surface coordinates"
(the size of texture that's being displayed) to "actor coordinates"
(the actor's allocation), but I can't find any place where the two are
different. As such, let's just go back to using "surface coordinates"
everywhere and see what breaks.
2014-02-05 14:05:18 -05:00
b8e096db82 Bump version to 3.11.5
Update NEWS.
2014-02-04 22:59:20 +01:00
3e98ffaf99 wayland-surface: Don't crash if a client destroys a buffer in use
This is considered "undefined" by upstream. Right now GTK+ does this
a lot, so we shouldn't crash. Let's make them crash instead and send
them an error instead.
2014-02-03 18:36:46 -05:00
0a9754f305 main: Squash constness warning 2014-02-03 18:02:16 -05:00
965a784c8a screen: Fix build
I thought I finished this patch last night... I guess not
2014-02-03 18:00:44 -05:00
2db9f55669 window-x11: Fix offscreen window match expression
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=723564
2014-02-03 17:34:52 -05:00
3e73babaf7 display: Clean up creation of the guard window a bit...
Do it consistently in all code paths...
2014-02-03 17:33:52 -05:00
66c4555dc7 main: Use setenv() 2014-02-03 17:33:52 -05:00
183ad75603 default plugin: Fix workspace switch type error
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=723563
2014-02-03 17:33:52 -05:00
66fc32ee14 core: remove tautological condition
unsigned number is always greater than 0

https://bugzilla.gnome.org/show_bug.cgi?id=720818
2014-02-02 15:23:40 +01:00
d6396cf2c4 window: fix coerced value
(int) 0.5 = 0, so there always was 0 instead of 50%
2014-02-02 15:17:29 +01:00
c9b7104117 monitorManager: Fix logic bug in make_logical_config
The code that prevents the creation of multiple MonitorInfos for clones
wasn't working due to using the wrong index when getting the already
created info so fix that to use the correct one.

https://bugzilla.gnome.org/show_bug.cgi?id=710610
2014-02-02 15:15:28 +01:00
6bf1a66b7c window_actor: Remove the frame_messages timeout in destroy
Otherwise it might fire off later and cause a crash.

https://bugzilla.gnome.org/show_bug.cgi?id=723468
2014-02-02 15:15:20 +01:00
7e7b671b8e keybindings: Simplify interface for VT switching 2014-02-01 19:38:01 -05:00
e04a55d1a2 keybindings: Reindent 2014-02-01 19:22:56 -05:00
8905bd2280 window-x11: Move meta_window_new to window-x11.c and rename 2014-02-01 19:19:22 -05:00
b09e1399c0 window: Centralize WM_STATE management 2014-02-01 19:18:01 -05:00
59c8b949ad window: Delay the showing of XWayland clients until set_window_id
Use our new "surface_mapped" field to delay the showing of XWayland clients
until we have associated together the window's XID and the Wayland surface ID.

This ensures that when we show this window to the compositor, it will properly
use the Wayland surface for rendering, rather than trying to use COMPOSITE and
crash.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-02-01 19:18:01 -05:00
6dbb3fddce window: Fix build once more
Bad syntax here...
2014-02-01 19:08:27 -05:00
f166240225 window: Clean up is_our_xwindow 2014-02-01 18:59:27 -05:00
91b789c707 window: Split out logic for determining whether an X window is ours 2014-02-01 18:59:27 -05:00
14db280fab window: Fix build
The proper function name is "meta_window_recalc_features"
2014-02-01 18:58:58 -05:00
f7097e6f66 Start moving X11-specific code to window-x11.c
The goal here is to make MetaWindow represent a toplevel, managed window,
regardless of if it's X11 or Wayland, and build an abstraction layer up.
Right now, most of the X11 code is in core/ and the wayland code in wayland/,
but in the future, I want to move a lot of the X11 code to a new toplevel, x11/.
2014-02-01 18:39:12 -05:00
ff89f1e271 window: Use window-props interface to load role/net_wm_type on init 2014-02-01 18:39:12 -05:00
6a8a4bfdcd window: Remove internal recalc_window_type / recalc_window_features
Just use the public symbols for them.
2014-02-01 18:39:12 -05:00
cd35982d4e window: Remove duplicated function declaration 2014-02-01 18:38:54 -05:00
2f6f0f252c wayland: Simply store a MetaWaylandBuffer
There's no need for the MetaWaylandBufferReference abstraction...
2014-02-01 17:55:16 -05:00
13651949ed wayland-seat: Rename sprite to cursor_surface 2014-02-01 17:55:03 -05:00
fdeb72224c wayland-seat: Fix pointer issues
Moving the mouse over weston-terminal, we can see several issues:

 * it often updates late, or not at all
 * the attachment of the pointer sprite is wrong

These are because we willy-nilly call seat_update_sprite all over the
place, and often in wrong areas. Set up a set_pointer_surface helper
method that will do the right thing for us in all cases, and call it
on transitions.
2014-02-01 17:54:47 -05:00
92e36e7076 wayland-surface: Attach the buffer to a surface, even if it doesn't have a role
Currently, set_cursor isn't properly working. Often, the requests look
like this:

  cursor_surface = wl_compositor.create_surface()
  cursor_buffer = create_cursor_buffer()
  cursor_surface.attach(cursor_buffer, 0, 0)
  cursor_surface.commit()
  wl_pointer.set_cursor(cursor_surface, 7, 14)

But since the surface doesn't "have a role" when the commit comes in,
we ignore it, and don't do anything with the pending buffer. When
set_cursor is called, however, we don't immediately update anything
since it doesn't have a buffer.

This effectively means that set_cursor has unpredictable side effects.
Weston's toy toolkit reuses the same surface for every buffer, so it
only fails the first time. In clients that use a new surface for every
cursor sprite, the cursor is effectively invisible.

To solve this, change the code to always set the buffer for a surface,
even if it doesn't have any real role.
2014-02-01 17:24:13 -05:00
d74796ee80 wayland-surface: Use the same commit() when commiting subsurface
Refactor our commit() implementation out of wl_surface_commit(),
and pass the double-buffered state around to all our implementation
methods. This allows us to drop a few lines destroying and
reinitializing list of frame callbacks. This is a big cleanup for
the next commit, though.
2014-02-01 16:44:18 -05:00
3e35cac67a wayland-surface: Repick after cleaning up everything else
Just a code cleanup to keep all the freeing code together.
2014-02-01 16:29:36 -05:00
1f7a6bf845 wayland-surface: Don't clean up the buffer_destroy_listener twice
double_buffered_state_destroy will do this for us.
2014-02-01 16:29:09 -05:00
365442c1ff wayland-surface: Fix typo 2014-02-01 16:19:54 -05:00
c8d185fc74 display: Revise Wayland event handling
X11 window frames use special UI grab ops, like META_GRAB_OP_CLICKING_MAXIMIZE,
in order to work properly. As the frames in this case are X11 clients, we need
to pass through X events in this case. So, similar to how handle_xevent works,
use two variables, bypass_clutter, and bypass_wayland, and set them when we
handle specific events.
2014-02-01 11:54:47 -05:00
9567fa9c6a wayland: Check for launcher before freeing it
This prevents a segfault on shutdown.
2014-01-31 19:03:56 -05:00
7a8de0c0af wayland: Reindent 2014-01-31 19:03:56 -05:00
10fead9ba1 wayland-pointer: Fix infinite loop when leaving focus from a destroyed surface
To prevent corruption, our focus listener needs to be removed even when
the surface is destroyed. So, bailing out when pointer->focus->resource
is NULL just isn't good enough.
2014-01-31 18:21:04 -05:00
d5d5c2167a compositor: Remove pending_input_region
Ever since the change to create the output window synchronously at startup,
there hasn't been any time where somebody could set a stage region the
output window was ready, so this was effectively dead code.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-31 17:21:00 -05:00
b9755ea725 window-actor: Remove old unused APIs
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-31 17:19:27 -05:00
39fee9f5a2 window-actor: Flip set_redirected around
I know it's confusing with the triple negative, but unredirected is how
we track it elsewhere: we have an 'unredirected' flag, and 'should_unredirect'.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-31 17:19:26 -05:00
d6282716b2 compositor: Simplify the unredirected window management code
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-31 17:19:26 -05:00
60d9bee3bf window-actor: Simplify the unredirected check in cull_out
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-31 17:19:26 -05:00
a09fa3b0e4 wayland: Clean up the parallels between creating callbacks and surface extensions 2014-01-31 16:40:47 -05:00
9edff6f250 wayland: Use wl_callback_send_done
For no specific reason...
2014-01-31 16:40:47 -05:00
7d3012fd67 screen: Make the guard window an InputOnly window
Using a full InputOutput window causes us to make a full Wayland surface
for it, and go through the X server. As the goal of the guard window is
a window for us to stack minimized windows under so we can prevent them
from getting input, it makes sense to use an InputOnly window here.
2014-01-31 14:19:42 -05:00
225e20a898 wayland: Remove superfluous "wayland_" from arguments 2014-01-31 11:38:37 -05:00
1a62ac9276 xwayland: Shuffle some code around 2014-01-31 11:24:02 -05:00
45cb151443 window-actor: Fix unobscured_region handling when computing paint volume
We currently ignore the unobscured region when we have mapped clones in
meta_window_actor_process_damage and meta_window_actor_damage_all but
use it unconditionally when computing the paint volume.

This is wrong. We should ignore it there as well or we will end up with
empty clones if the cloned window is completly obscured
(like the tray icons in gnome-shell).

https://bugzilla.gnome.org/show_bug.cgi?id=721596
2014-01-31 15:16:48 +01:00
55b18f9671 window: Add "skip-taskbar" property
We currently only have a method to query the skip-taskbar hint.
Add a corresponding property to allow listening for change
notifications.

https://bugzilla.gnome.org/show_bug.cgi?id=723307
2014-01-31 13:33:38 +01:00
4f4b1bfc37 wayland: Support wl_subsurface.set_sync/set_desync
Implement support for synchronous subsurfaces commits. This means that
the client can, by calling wl_subsurface.set_sync, cause its surface
state to be commited not until its parent commits.

This will mean there will be will potentially be one more surface state
(regions, buffer) at the same time: the active surface state, the mutable
pending surface state, and the immutable surface state that was pending
on last surface commit.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2014-01-30 15:13:44 -05:00
9348c9bd4b wayland: Make wl_subsurface.place_(above|below) properly synchronized
The placement set by either wl_subsurface.place_above or
wl_subsurface.place_below should be applied when the parent surface
invokes wl_surface.commit.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2014-01-30 15:13:43 -05:00
16de7f66fb wayland: Make wl_subsurface.set_position properly synchronized
The position set by wl_subsurface.set_position should be applied when
the parent surface invokes wl_surface.commit.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2014-01-30 19:12:06 +01:00
799c27484d wayland: Report error when trying to stack subsurface incorrectly
Don't allow a client to stack a subsurface next to a subsurface with
another parent, or to a non-parent non-subsurface surface.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2014-01-30 19:12:06 +01:00
c3b0faec82 main: Make sure to free any events that we get from Clutter 2014-01-29 14:03:43 -05:00
9c876722a0 xwayland: Use server protocol wrappers instead of wl_resource_post_event 2014-01-29 10:27:16 -05:00
96fc93d744 xwayland: Reindent 2014-01-29 10:23:58 -05:00
20545941fa Revert unintentional merge from wip/surface-content to wayland
This reverts a lot of commits.
2014-01-22 09:18:13 -05:00
59f79e8294 constraints: CSD windows need to have their titlebar kept onscreen too
GTK+ CSD windows are considered undecorated by the code, so we should
not force ourselves to only run on decorated windows.

https://bugzilla.gnome.org/show_bug.cgi?id=719772
2014-01-22 09:15:59 -05:00
ac32b9ef95 get xwayland working again 2014-01-21 19:06:06 -05:00
ba484be754 window-actor: Don't use TFP under XWayland
Simply have a NULL surface actor until the set_window_id arrives...
2014-01-21 19:01:34 -05:00
a318198ab4 xwayland: Update the surface actor for the window on set_window_id
We need to do this for XWayland windows, since we only get the event
telling us they're an XWayland window after the compositor knows about
the window.
2014-01-21 19:01:34 -05:00
e6391c2896 surface content 2014-01-21 19:01:34 -05:00
7ea537fad7 Move position-changed / size-changed signals to the MetaWindow
They fit more appropriately over here...

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-21 19:01:34 -05:00
03146c2967 window-actor: Remove old unused APIs
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-21 19:01:34 -05:00
0a81314337 window-actor: Flip set_redirected around
I know it's confusing with the triple negative, but unredirected is how
we track it elsewhere: we have an 'unredirected' flag, and 'should_unredirect'.

https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-21 19:01:34 -05:00
fa7a5782c6 compositor: Simplify the unredirected window management code
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-21 19:01:34 -05:00
e3b64912b6 window-actor: Simplify the unredirected check in cull_out
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-21 19:01:34 -05:00
a0fe392665 surface-actor: Move unobscured_region processing here
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-21 19:01:34 -05:00
0e5f365d55 compositor: Remove pending_input_region
Ever since the change to create the output window synchronously at startup,
there hasn't been any time where somebody could set a stage region the
output window was ready, so this was effectively dead code.
2014-01-21 19:01:34 -05:00
bfc906cbc4 compositor: Remove meta_compositor_window_[un]mapped
We no longer unmap the toplevel windows during normal operation. The
toplevel state is tied to the window's lifetime.

Call meta_compositor_add_window / meta_compositor_remove_window instead...
2014-01-21 19:01:34 -05:00
8e6f8087e8 Always map the client and frame windows
Traditionally, WMs unmap windows when minimizing them, and map them
when restoring them or wanting to show them for other reasons, like
upon creation.

However, as metacity morphed into mutter, we optionally chose to keep
windows mapped for the lifetime of the window under the user option
"live-window-previews", which makes the code keep windows mapped so it
can show window preview for minimized windows in other places, like
Alt-Tab and Expose.

I removed this preference two years ago mechanically, by removing all
the if statements, but never went through and cleaned up the code so
that windows are simply mapped for the lifetime of the window -- the
"architecture" of the old code that maps and unmaps on show/hide was
still there.

Remove this now.

The one case we still need to be careful of is shaded windows, in which
we do still unmap the client window. Theoretically, we might want to
show previews of shaded windows in the overview and Alt-Tab, so we remove
the complex unmap tracking for this later.
2014-01-21 19:01:18 -05:00
56207ddb6a window-actor: Never unredirect when under Wayland
https://bugzilla.gnome.org/show_bug.cgi?id=720631
2014-01-20 16:14:56 -05:00
8cb9cfb7b8 Revert "meta-weston-launch: Call VT_ACTIVATE ourselves"
This reverts commit ebe6e3180e.

This is wrong, as mutter's controlling TTY may not be the same
as the active VT, and in fact won't be in the case of systemd
spawning us.

The "correct" API for this is to use David Herrmann's
"Session Positions" system to switch to another VT:

  http://lists.freedesktop.org/archives/systemd-devel/2013-December/014956.html
2014-01-16 13:42:07 -05:00
be698b597b shaped-texture: Use a double when calculating clip
For x defined below, x == -INT32_MAX assuming that the arithmetic
expression actually uses the fpu.

float f = 1.0f;
int32_t x = INT32_MAX * f;

This would result in the calculated clip width/height to be -INT_MAX
if the damage width/height is INT_MAX. To solve this, use a double
variable instead.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2014-01-16 13:27:59 -05:00
1d61a0f9b5 Bump version to 3.11.4
Update NEWS.
2014-01-16 10:42:11 -05:00
788bd59857 cursor-tracker: Rely on gbm_bo_imports()'s buffer validation
cogl_texture_get_format() has been deprecated, so rather than using
it to figure out beforehand whether the buffer format is supported,
just rely on the import failing if it isn't.

https://bugzilla.gnome.org/show_bug.cgi?id=722347
2014-01-16 10:18:32 -05:00
2391606cc5 cursor-tracker: Update for Cogl APIs as well 2014-01-13 13:55:58 -05:00
7155d7e043 Properly set the number of components on the CoglTextureRectangle
We need to set the number of components on the CoglTextureRectangle to
prevent wasting too much GPU memory. As we need to do this before we call
cogl_texture_set_region, just remove the meta_texture_rectangle_new wrapper,
and make callers call cogl_texture_rectangle_new_with_size directly.
2014-01-13 13:28:38 -05:00
419dfd333a Update for Cogl API breaks 2014-01-13 13:08:17 -05:00
b4535f2622 Updated obsolete FSF postal address in COPYING
Fixed https://bugzilla.gnome.org/show_bug.cgi?id=721517 #1
2014-01-13 11:35:48 -05:00
9b21346427 Changed obsolete FSF postal address into generic URL.
Fix https://bugzilla.gnome.org/show_bug.cgi?id=721517 #2
2014-01-13 11:35:47 -05:00
7b15d21e40 monitor: Suppress -Werror=unused-variable
Fallout from 477acddf64

https://bugzilla.gnome.org/show_bug.cgi?id=721674
2014-01-13 11:35:47 -05:00
7b597b8c62 monitor: improve heuristic to determine display output name
Under some circumstances, for example when the display controller driver
doesn't report back the correct EDID, or under VirtualBox, Mutter
returns suboptimal strings for an output display name, leading to funny
labels like 'Unknown 0"', or '(null) 0"' in the Settings panel.

This commit improves our heuristic in three ways:
- we now avoid putting inches in the display name if either dimension is
  zero
- we use the vendor name in case we're not able to lookup its PnP id
  from the database. Previously we would have passed over '(null)'
- as a special edge-case, when neither inches nor vendor are known, we
  use the string 'Unknown Display'

Finally, we make the combined vendor + inches string translatable, as
different languages might want to move the size part of the string to a
position different than the end.

https://bugzilla.gnome.org/show_bug.cgi?id=721674
2014-01-13 11:35:47 -05:00
7a4adce44f window: Atomically unmaximize both directions from a _NET_WM_STATE ClientMessage
When GDK sends an unmaximize _NET_WM_STATE ClientMessage, it tells us to remove
the _NET_WM_STATE_MAXIMIZED_HORZ and _NET_WM_STATE_MAXIMIZED_VERT states. Before
this time, it would independently call:

  meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
  meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);

Which, besides being foolishly inefficient, would also mess up our saved_rect
tracking, causing the window to only look like it was unmaximized vertically.

Make this code more intelligent, so it causes us to unmaximize in one call.

https://bugzilla.gnome.org/show_bug.cgi?id=722108
2014-01-13 11:35:47 -05:00
a5f0db5ecb window: don't grab server during calc_showing
This grab was added in commit caf43a123f
https://bugzilla.gnome.org/show_bug.cgi?id=381127
to minimize window flickering when switching workspaces.

While this grab is held, some signals are emitted to the shell,
which can lead to deadlocks (reproduced under Mali binary OpenGLESv2
drivers).

Now that we are a compositing window manager, we do not have to
worry about flickers, this grab should no longer be necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=721709
2014-01-07 14:27:24 -06:00
577624adef Reduce server grabs during window creation
Remove some obvious server grabs from the window creation codepath,
also ones that are taken at startup.

During startup, there is no need to grab: we install the event handlers
before querying for the already-existing windows, so there is no danger
that we will 'lose' some window. We might try to create a window twice
(if it comes back in the original query and then we get an event for it)
but the code is already protected against such conditions.

When windows are created later, we also do not need grabs, we just need
appropriate error checking as the window may be destroyed at any time
(or it may have already been destroyed).

The stack tracker is unaffected here - as it listens to CreateNotify and
DestroyNotify events and responds directly, the internal stack
representation will always be consistent even if the window goes away while
we are processing MapRequest or similar.

Now that there are no grabs we don't have to worry about explicitly calling
display_notify_window after grabs have been dropped. Fold that into
meta_window_new_shared().

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-07 07:53:16 -06:00
af46ef3b96 meta_window_new: clean up error handling
The return code of XGetWindowAttributes() indicates whether an error
was encountered or not. There is no need to specifically check the error
trap.

The trap around XAddToSaveSet() was superfluous. We have a global error
trap to ignore any errors here, and there is no need to XSync() as GDK
will later ignore the error asynchronously if one is raised.

Also move common error exit path to an error label.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-07 07:44:31 -06:00
39d26be941 screen: use stack tracker for initial window query
In meta_screen_manage_all_windows() we can use our own stack
tracker to get the list of windows - no need to query X again.

A copy is needed because the stack gets modified as part of the loop.
Specifically, meta_stack_tracker_get_stack() at this time returns the
predicted stack, and meta_window_new() performs a few operations
(e.g. framing) which cause immediate changes to the predicted stack.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-07 07:44:31 -06:00
7bfc9109f7 frame: remove unnecessary server grab
meta_window_ensure_frame() creates its own grab and has a comment
claiming that it must be called under a grab too.

But the reasoning given in the comment does not seem relevant here.
We only frame non-override-redirect windows, so we are creating
the frame in response to MapRequest. There is no way that the child
could receive a MapNotify at this point, since that only happens
much later, once we go through the CALC_SHOWING queue and call
XMapWindow() from meta_window_show().

Remove the unnecessary grab.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-07 07:17:09 -06:00
becbad56ef Discourage server grabs
Server grabs are not as evil as you might expect, but there is agreement
in that their usage should be limited.

Server grabs can cause things to go rather wrong when mutter emits
a signal while it has grabbed the server. If the receiver of that signal
waits for a synchronous action performed by another client, then you
have a deadlock. This happens with Mali binary GLESv2 drivers :(

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-07 07:17:09 -06:00
384a34c27d Remove meta_window_new_with_attrs
The compositor code used to handle X windows that didn't have a
corresponding MetaWindow (see commit d538690b), which is why the
attribute query is separated.

As that doesn't happen any more, we can clean up. No functional changes.

Suggested by Owen Taylor.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-07 07:17:06 -06:00
002c5b8f87 wayland: Don't keep track of the drm FD in the WaylandCompositor
As logind can give us a new FD at any time when it resumes. Theoretically,
this is still technically wrong, as the MetaCursorTracker holds onto it.
We'll fix this after we port to logind.
2013-12-31 19:22:16 -05:00
1d3dbea20c meta-weston-launch: Don't use a GObject here
We don't need a complicated API anymore.
2013-12-31 19:22:16 -05:00
ebe6e3180e meta-weston-launch: Call VT_ACTIVATE ourselves
We don't need any special permissions, so we don't need to go through
weston-launch to do so...
2013-12-31 19:22:16 -05:00
a3de799939 wayland-surface: Remove inappropriate meta-weston-launch.h include 2013-12-31 19:20:58 -05:00
0caf7381bb display: Don't leave focus on a window we are unmanaging when sending WM_TAKE_FOCUS
When we move focus elsewhere when unmanaging a window, we *need* to move
the focus, so if the target is globally active, move the focus to the
no-focus-window in anticipation that the focus will normally get moved
to the right window when the target window responds to WM_TAKE_FOCUS.

If the window doesn't respond to WM_TAKE_FOCUS, then focus will be left
on the no-focus-window, but there's no way to distinguish whether the
app will respond or not.

https://bugzilla.gnome.org/show_bug.cgi?id=711618
2013-12-24 11:30:14 -05:00
a42305edab Be willing to unfocus the grab window when we are unmanaging it
When we are unmanaging the grab window, we /need/ to unfocus it,
so we shouldn't bail out early from meta_window_focus().

https://bugzilla.gnome.org/show_bug.cgi?id=711618
2013-12-24 11:30:11 -05:00
732c059235 Bump version to 3.11.3
Update NEWS.
2013-12-19 19:34:06 +01:00
ef2b6e7d00 window-actor: Fix optimization in get_paint_volume
We need to clip the paint volume to the unobscured region, not the
other way around...

https://bugzilla.gnome.org/show_bug.cgi?id=720630
2013-12-18 18:43:39 -05:00
9c1b972ca1 Fix problems with focus tracking
When a client spontaneously focuses their window, perhaps in response
to WM_TAKE_FOCUS we'll get a FocusOut/FocusIn pair with same serial.
Updating display->focus_serial in response to FocusOut then was causing
us to ignore FocusIn and think that the focus was not on any window.

We need to distinguish this spontaneous case from the case where we
set the focus ourselves - when we set the focus ourselves, we're careful
to combine the SetFocus with a property change so that we know definitively
what focus events we have already accounted for.

https://bugzilla.gnome.org/show_bug.cgi?id=720558
2013-12-18 09:46:08 -05:00
cb33e1942a meta_window_move_resize_internal: handle border size changes
Initial placement during meta_window_constrain() can result in changes
to the borders, so we need to recompute our border sizes after
constraining. This fixes incorrect window borders on
initially maximized windows.

https://bugzilla.gnome.org/show_bug.cgi?id=720417
2013-12-18 09:30:22 -05:00
7009d1e470 wayland: Update to latest xdg-shell
We don't use the new maximize / fullscreen request system yet, leading
to broken maximization / fullscreen. This will be fixed in a followup.
2013-12-17 15:04:16 -05:00
c54a19825b keybinding: Implement keybindings for moving windows between monitors
Currently the only way to move a window to another monitor via
keyboard is to start a move operation and move it manually using
arrow keys. We do have all the bits of a dedicated keybinding in
place already, so offer it as a more comfortable alternative.

https://bugzilla.gnome.org/show_bug.cgi?id=671054
2013-12-12 09:13:17 +01:00
8131f34eb6 Move _NET_WM_WINDOW_OPACITY handling to the standard window-props interface 2013-12-09 15:53:23 -05:00
f29241d90e compositor: Remove atom_x_root_pixmap
It's unused
2013-12-09 15:53:23 -05:00
bad48ea815 introspection: Make MetaKeyHandlerFunc compatible with master
This allows gnome-shell's JS handlers work on the wayland branch.
2013-12-09 21:34:53 +01:00
66af41f4a9 window-actor: Remove outdated code path
The shadow is added in the paint step, not as a separate actor,
so the raise is a no-op. It also gets rid of an annoying misspelling
that's driving me crazy.
2013-12-09 14:10:44 -05:00
e30be380dd window-actor: Move signal handler connections to the meta-window setter 2013-12-09 14:08:01 -05:00
65f2e29375 window-actor: Make the meta-window property construct-only
We don't deal with setting this property at all, and it's unlikely
to come up in future settings, so just don't allow setting it at all.

https://bugzilla.gnome.org/show_bug.cgi?id=678989
2013-12-09 14:08:01 -05:00
98dbba1e17 window-actor: Remove meta-screen property
This can be inferred from the window. Don't allow anybody to set it.

https://bugzilla.gnome.org/show_bug.cgi?id=678989
2013-12-09 14:05:18 -05:00
422648e2eb window-actor: Remove (private) xwindow property
This should make it easier to construct a MetaWindowActor from bindings.

https://bugzilla.gnome.org/show_bug.cgi?id=678989
2013-12-09 14:05:18 -05:00
f0fa4d831a window: Add a simple meta_window_get_toplevel_xwindow utility
To replace all the places where we do:

  window->frame ? window->frame->xwindow : window->xwindow

or similar...
2013-12-09 14:05:18 -05:00
1b600f5867 window-actor: Use g_signal_connect_object
To make our signal connections a bit more manageable...
2013-12-09 13:57:33 -05:00
fd8cc9b7a8 xwayland: Remove outdated code
Now that focus management goes through the central display.c,
we don't need to do this separately. Wayland and X clients
should just behave as one.
2013-12-09 13:57:32 -05:00
ca5b5e6bc4 surface-actor: Reindent 2013-12-06 20:28:39 -05:00
ee683ff187 window: Fix meta_window_ping some more
Make sure to actually add the pings to the list... and don't
remove it from the list twice.
2013-12-06 20:23:00 -05:00
57602adfe7 surface-actor: Don't use self->priv->foo directly
I don't like it...
2013-12-06 20:10:21 -05:00
1481836ed6 surface-actor: Move work out of _new constructor
If we want to have any chance at creating subclasses of MetaSurfaceActor,
we can't do work in the constructor...
2013-12-06 20:10:21 -05:00
309f78ff52 display: Fix window pings
These are 32-bit values, not longs. Treat them as such.
2013-12-06 20:03:46 -05:00
6436459381 xrandr: ignore the error if setting the primary output fails
Some drivers which support RandR 1.4 may not support setting
or getting the primary output, therefore mutter should trap
and ignore any relevant errors.

The modesetting driver exposes this problem when used in
combination with the nvidia binary driver using RandR 1.4
offloading.

Also use a local display variable instead of calling
meta_get_display () every time.
2013-12-06 15:30:53 -05:00
65b39212d5 meta-wayland: Remove undefined variable 2013-12-05 18:32:11 -05:00
283649b8d7 Support keybindings again, too 2013-12-05 17:18:49 -05:00
fa65c380db Support X button events again
Do this by duplicating the current code and porting it to use
X again. A better approach would involve our own event structures,
and I really don't want to do that right now. We can clean this up
later.
2013-12-05 17:18:49 -05:00
58b39233f5 display: Correct the detection of a grab
The grab_window might be NULL, in which case we have a full-screen
grab, but we might still in a grab. Correct the check by asking
whether we're in a grab op or not.
2013-12-05 17:18:49 -05:00
82066e02c5 display: Set the cursor when calling XIGrabDevice again 2013-12-05 17:18:49 -05:00
c36aa5e696 cursor-tracker: Don't assume we're a Wayland compositor 2013-12-05 17:18:49 -05:00
29197d40c6 compositor: Don't assume we're a Wayland compositor 2013-12-05 17:18:49 -05:00
8d5ab6b5b3 Use the correct frame size during unmaximize
When unmaximizing, we changed bits of window state, then called out
to code that used the frame extents *before* we cleared old cached
extents. Clear the cache up-front as soon as we change the window
state.

https://bugzilla.gnome.org/show_bug.cgi?id=714707
2013-12-05 11:17:32 -05:00
a796938b39 MetaWindowGroup: fix paint volume
In the past, MetaWindowGroup was allocated the size of the screen and
painted the size of the screen because it contained the screen background,
but now we also have the "top window group" which contains only popup
windows, so the allocation doesn't properly reflect the paint bounds
of the window group. Compute the paint bounds accurately from the
children.

https://bugzilla.gnome.org/show_bug.cgi?id=719669
2013-12-05 09:06:33 -05:00
3813113f1a window-props.c: React to changes to _GTK_FRAME_EXTENTS
When _GTK_FRAME_EXTENTS changes, we need to redo constraints on
the window - this matters in particular if the toolkit removes
invisible borders when a window is maximized, since otherwise
the maximized window will be positioned as if it still has
invisible borders.

https://bugzilla.gnome.org/show_bug.cgi?id=714707
2013-12-05 09:06:26 -05:00
1be117e430 wayland-surface: Properly set the window type
We need to make sure to call meta_window_type_changed after updating
the type...
2013-12-04 10:41:58 -05:00
622c7a021b window-actor: Update shape at construction time
When we attach an existing surface actor, the allocation may not
change, so we need to ensure that the shape region and geometry is
valid...
2013-12-04 10:26:06 -05:00
4d2d2f285b core: window: enable create effect for new wayland windows
https://bugzilla.gnome.org/show_bug.cgi?id=719833
2013-12-04 11:14:30 +00:00
0924c7d61b wayland: Use a stage paint callback instead of a signal handler on "paint"
This is much more appropriate...
2013-12-03 14:49:40 -05:00
2746608eb2 background-actor: Remove custom get_paint_volume
The paint volume should be based on what we paint, not what the content
wants to be painted as. Thus, it should be the allocation.
2013-12-03 14:36:29 -05:00
fe26cb5989 wayland-surface: Unmanage the window when destroying xdg_surface/xdg_popup
Also, unparent the actor when destroying a subsurface, as well, and
don't free the surface when we destroy the MetaWindow.
2013-12-03 11:45:50 -05:00
602307e694 Revert "pointer: Remove focus listener"
This reverts commit a8ac2cc275.
2013-12-03 11:45:50 -05:00
b2c18c4a78 Revert "keyboard: Remove focus listener"
This reverts commit 0ac142d39e.
2013-12-03 11:45:50 -05:00
1e211722c7 wayland-surface: Set popups transient to their parents 2013-12-03 11:45:50 -05:00
461f74ef18 wayland: Fix setting keyboard/pointer focus for new clients
When we have a new client, we potentially set the focus on one of its
surfaces when we map it but the client might not have called
wl_seat.get_keyboard/pointer yet. When it finally calls
get_keyboard/pointer we must then register its resource as the
focus_resource which means that we can only return early if
focus_resource is already set.

https://bugzilla.gnome.org/show_bug.cgi?id=719725
2013-12-03 15:56:15 +01:00
3f022ca963 window: Possibly set the pointer focus on newly mapped wayland windows
Windows showing up under the pointer must get the pointer focus.

https://bugzilla.gnome.org/show_bug.cgi?id=719725
2013-12-03 15:56:15 +01:00
20e92c5a72 wayland: Set the clutter stage focus when we focus a window
Otherwise clutter events don't have their source actor properly set
and we aren't able to determine the MetaWindow to which a given
keybinding applies.

https://bugzilla.gnome.org/show_bug.cgi?id=719724
2013-12-03 13:58:27 +01:00
0850da44d7 shaped-texture: Prevent a critical when setting a NULL cogl texture 2013-12-02 21:34:23 -05:00
37ba264190 compositor: meta-surface-actor: upload texture changes at the correct position
https://bugzilla.gnome.org/show_bug.cgi?id=719695
2013-12-02 16:41:29 +00:00
6c12c928df compositor: Update to latest cogl API
See https://git.gnome.org/browse/cogl/commit/?id=c76c1d136d2cac7f3d1331a4d1dc0dd0f06e812c

https://bugzilla.gnome.org/show_bug.cgi?id=719557
2013-11-29 11:08:51 -05:00
9c5733caf0 prefs: Properly add new META_KEYBINDING_ACTION_* value
In addition to 4373916d9d

(cherry picked from commit 3b2506851c)
2013-11-29 16:33:42 +01:00
21d8b8310a window: Proper argument naming for meta_window_client_rect_to_frame_rect
(cherry picked from commit 9b88059e55)
2013-11-29 16:33:37 +01:00
c46af91d54 window: Fix deprecated version of get_outer_rect
(cherry picked from commit 59168b2c64)
2013-11-29 16:32:15 +01:00
d44574f738 wayland-surface: Process damage even if the buffer didn't change 2013-11-26 12:32:41 -05:00
a9424255a5 wayland-surface: Add support for subsurfaces
The state for a subsurface isn't double-buffered yet, though...
2013-11-25 18:33:03 -05:00
5089a63d76 wayland-surface: Create the surface actor ourselves
Otherwise, we can't rely on a surface_actor being around to add
ourselves to...
2013-11-25 18:29:58 -05:00
f9a2c64460 wayland-surface: Don't require a MetaWindow to process damage...
and ClutterActor will clip to the actor bounds, anyway...
2013-11-25 18:15:20 -05:00
7841042a85 wayland-surface: Restructure code flow in wl_surface_attach a bit more... 2013-11-25 18:15:20 -05:00
ea1b8cdc22 wayland-surface: Fix copy/paste typo 2013-11-25 18:15:19 -05:00
52b48cfbef wayland-surface: Return after posting errors back to the client 2013-11-25 18:15:03 -05:00
644f3e1275 window: Make setters for shape/input/opaque regions private again
Wayland now pushes these to the surface actor rather than the toplevel
MetaWindow...
2013-11-25 17:25:56 -05:00
304005e04f wayland-surface: Replace MetaWindowActor with MetaSurfaceActor
Since subsurfaces won't have toplevel MetaWindowActors, we need to
use MetaSurfaceActor instead. These are embedded in the MetaWindowActor,
just like MetaShapedTexture was (in fact, MetaSurfaceActor now contains
a MetaShapedTexture)
2013-11-25 17:25:55 -05:00
025ab35af7 surface-actor: Add setters for set_input_region / set_opaque_region
Subsurfaces won't have a MetaWindow or MetaWindowActor to fetch these from,
so they need to be tied directly to the MetaSurfaceActor.
2013-11-25 17:25:47 -05:00
a27744503b shaped-texture: Make Cullable
Make MetaWindowActor chain up to the generic default MetaCullable
implementation, and remove the helper methods for MetaSurfaceActor
and MetaShapedTexture.
2013-11-25 17:25:47 -05:00
1011331caf cullable: Use relative actor coordinates for culling
This ensures that nested cullables work fine.
2013-11-25 17:25:47 -05:00
0ccef81789 wayland-surface: Rework flow control for wl_surface_commit 2013-11-25 17:25:46 -05:00
4780f74a40 wayland-surface: Properly allow setting the cursor to a NULL buffer 2013-11-25 17:18:22 -05:00
57866fb267 wayland-surface: Don't rewrite input/opaque regions if the client doesn't attach any 2013-11-25 17:18:22 -05:00
d3bc7570d0 window-actor: Update the shape region when the surface actor changes size 2013-11-25 17:18:22 -05:00
74e43a4702 cullable: Turn cull_out / reset_culling into a separate interface
Instead of hardcoded knowledge of certain classes in MetaWindowGroup,
create a generic interface that all actors can implement to get parts of
their regions culled out during redraw, without needing any special
knowledge of how to handle a specific actor.

The names now are a bit suspect. MetaBackgroundGroup is a simple
MetaCullable that knows how to cull children, and MetaWindowGroup is the
"toplevel" cullable that computes the initial two regions. A future
cleanup here could be to merge MetaWindowGroup / MetaBackgroundGroup so
that we only have a generic MetaSimpleCullable, and move the "toplevel"
cullability to be a MetaCullableToplevel.

https://bugzilla.gnome.org/show_bug.cgi?id=714706
2013-11-25 15:21:36 -05:00
0764b2058a window-actor: Move the operations we need to do when we cull out here
Soon, we'll move this into a generic MetaCullable interface, but for
now, just put hardcoded knowledge in MetaWindowGroup.

https://bugzilla.gnome.org/show_bug.cgi?id=714706
2013-11-25 15:19:08 -05:00
7a787d7946 window-group: Decompose culling operations into two methods
This also fixes a bug in the translation of clip_region.

We will add an interface for this soon, so we can recursively cull like this...

https://bugzilla.gnome.org/show_bug.cgi?id=714706
2013-11-25 15:18:09 -05:00
eec0f5df47 display: Fix logic for determining whether our focus was successful
In some cases, we can focus the frame window instead of the client
window, so make sure that our checks include that as well.

https://bugzilla.gnome.org/show_bug.cgi?id=715030
2013-11-25 15:14:18 -05:00
ba3968a822 keybindings: Fix typo in port to Clutter events
We always want to trigger on key press.
2013-11-25 14:15:28 +01:00
762fa0e116 compositor: Also redirect windows in wayland compositor mode
XWayland was doing this for us but now it isn't anymore.
2013-11-25 12:00:55 +01:00
0be57b621b window-actor: Fix a copy/paste typo 2013-11-21 17:35:52 -05:00
7d88b3593b surface-actor: Remove unused field 2013-11-21 17:29:41 -05:00
858db7081a background-group: Fix cast warning 2013-11-21 15:14:40 -05:00
5af7f619c8 background-group: Use the Clutter iteration APIs 2013-11-21 14:24:32 -05:00
e5e35e5a7f background-group: Remove some unnecessary cruft 2013-11-21 14:24:32 -05:00
6d639ac528 window: Support pinging Wayland surfaces as well 2013-11-21 14:24:04 -05:00
aa3643cdde Move window pings to MetaWindow
This will make it possible to use on Wayland as well...
2013-11-21 14:24:04 -05:00
8a3501ffe1 xwayland: Fix a couple of small leaks
https://bugzilla.gnome.org/show_bug.cgi?id=712833
2013-11-21 19:22:26 +01:00
5ea443eb4b idle-monitor: Fix a GSList leak
https://bugzilla.gnome.org/show_bug.cgi?id=712833
2013-11-21 19:22:25 +01:00
a37a8c6497 wayland-surface: Fix transient_for
It takes a wl_surface resource, not an xdg_shell_surface resource,
and the argument is allowed to be NULL.
2013-11-21 13:09:21 -05:00
ebf6862a10 wayland-surface: Don't mark popup windows as override-redirect 2013-11-21 13:09:21 -05:00
6c0e16c482 keybindings: Properly interpret keybindings
We need to compare against the keysym, not the keycode.
2013-11-21 13:09:21 -05:00
40b1e7312d Update xdg-shell.xml 2013-11-21 13:09:21 -05:00
1c0e6f26e2 mutter-launch: Don't test the argument name to validate launching things
Somebody could do:

  $ mv my-evil-program mutter-wayland
  $ PATH=.:$PATH mutter-launch mutter-wayland

It's not secure, and it's hard to test with, so just drop it for now
We'll be relying on logind to hand us permissions in the future.
2013-11-20 17:07:03 -05:00
f4fc498e65 wayland-surface: Properly destroy extension resources on the destroy request
Otherwise, the resource IDs will linger around and be destroyed again
on client close...
2013-11-19 23:34:03 -05:00
a8632c2546 Revert "wayland-surface: Allow extension resources to be double-destroyed"
This reverts commit 2ebecc5370.
2013-11-19 23:34:03 -05:00
600a0f836f keyboard: Don't send leave events to dying surfaces 2013-11-19 20:26:28 -05:00
0ac142d39e keyboard: Remove focus listener 2013-11-19 20:26:28 -05:00
abd368be00 pointer: Don't send leave events to dying surfaces
It's invalid and will crash the client.
2013-11-19 20:26:03 -05:00
a8ac2cc275 pointer: Remove focus listener
It's added too late to matter -- by the time we've destroyed the
resource, we've already repicked and re-set the focus.
2013-11-19 20:26:03 -05:00
2f14b5cc3f wayland: Set a log handler
To see error messages and such
2013-11-19 20:26:02 -05:00
2930612e64 pointer: Remove dead and incorrect code
Now that we can never pick a destroying actor, we can remove these
bad asserts.
2013-11-19 19:35:34 -05:00
2952d3671d window-actor: Set as unreactive when hiding
This means that we should never pick the actor when it's being destroyed.
2013-11-19 19:35:34 -05:00
1b5ace8256 window-actor: Don't set ourselves as reactive twice 2013-11-19 19:35:34 -05:00
2ebecc5370 wayland-surface: Allow extension resources to be double-destroyed
As they will be on shutdown... I'm not sure if this is a wayland-server
bug or not, but we should guard against it anyway.
2013-11-19 19:35:34 -05:00
02144d17e9 wayland-surface: Fill in the maximized/fullscreen hints to the configure event 2013-11-19 19:35:34 -05:00
71496c8909 Update xdg-shell.xml 2013-11-19 19:01:16 -05:00
594b15abf1 pointer: Fix crash when we have the pointer over nothing during a popup grab 2013-11-19 18:51:30 -05:00
bbe3641844 wayland-surface: Add support for xdg_popup 2013-11-19 18:44:21 -05:00
0cc5cf940b wayland-surface: Remove some properties from the double-buffered state
Now that we can always set them on the MetaWindow...
2013-11-19 18:44:21 -05:00
153d8efcf5 window: Create a backing MetaWindow for unmapped Wayland surfaces
We require a MetaWindow to properly implement some of the requests
for xdg_surface, so add a way to have an unmapped MetaWindow that
we can store properties on, that we later map when the client
attaches a buffer...
2013-11-19 17:48:19 -05:00
be744775c1 wayland-surface: Support xdg_surface.destroy
Cool.
2013-11-19 17:48:19 -05:00
5959457c73 wayland-surface: Embed MetaWaylandSurfaceExtension in MetaWaylandSurface
This makes it easier to support xdg_surface.destroy, which we're
going to add support for next commit...
2013-11-19 17:48:19 -05:00
0824eb7c96 cursor-tracker: Make sure to sync after we change the cursor
So the cursor changes immediately...
2013-11-19 15:43:46 -05:00
d945501be6 window: Remove width/height from meta_window_new_for_wayland 2013-11-19 15:37:33 -05:00
ca342c4573 window: Remove unused parameter from meta_window_new_shared() 2013-11-19 15:37:33 -05:00
4326d0bf3a compositor: Make sure to construct plugin_mgr in Wayland as well... 2013-11-19 15:37:31 -05:00
a6ebc70170 Bump version to 3.11.2
Update NEWS.
2013-11-19 20:15:13 +01:00
3025cb7c48 display: Remove unused variables 2013-11-19 20:12:51 +01:00
17f48baf3a display: Tweak code to work around a compiler warning
The compiler is not quite smart enough to figure out that the condition
for setting the "compositor" variable matches a later condition for
accessing it, so express this in a way the compiler will understand.
2013-11-19 20:08:46 +01:00
333661a9d8 stack: Drop unused code
Since commit 2b2b2d3191 the code is unused and triggers a
compiler error with -Werror=unused-but-set-variable.
2013-11-19 20:08:46 +01:00
b9da43b753 Rename meta_window_get_outer_rect() to meta_window_get_frame_rect()
For clarity, rename meta_window_get_outer_rect() to match terminology
we use elsewhere. The old function is left as a deprecated
compatibility wrapper.
2013-11-19 14:04:16 -05:00
097ee776c7 Stop passing around MetaFrameBorders
Instead of passing around MetaFrameBorders, compute it when we need it.
This also allows us to know that we are using MetaFrameBorders only for windows
with frames (where it is meaningful) and not for frameless windows, which
can have custom borders which we need to interpret differently.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 14:04:16 -05:00
a4a8f1f863 MetaFrame: Cache borders
Cache the computed border size so we can fetch the border size at
any time without worrying that we'll be spending too much time in
the theme code (in some cases we might allocate a PangoFontDescription
or do other significant work.)

The main effort here is clearing the cache when various bits of window
state change that could potentially affect the computed borders.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 14:04:16 -05:00
f36a627330 Use utility functions to convert between frame and client rectangles
There are extensive places in the code where we convert between the client
rectangle and the frame rectangle. Instead of manually doing it use
new helper functions on MetaWindow and the existing meta_window_get_outer_rect().

This fixes a number of bugs where the computation was being done incorrectly,
most of these bugs are with the recently added custom frame extents, but
some relate to invisible borders or even simply to confusion between the
window and frame rectangle.

Switch the placement code to place the frame rectangle rather
than the client window - this simplifies things considerably.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 14:04:16 -05:00
a1087c3f30 constraints: account for decorations when positioning modal dialogs
What we want to achieve is that the dialog is visually centered
on the parent, including the decorations for both, and making sure
that CSD/frame_extents are respected.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 14:04:16 -05:00
aad275b9a2 window: Fix signedness warning 2013-11-19 14:03:09 -05:00
f0397eab94 keybindings: Fix warning
keybinding handlers now take a ClutterEvent, not an XIDeviceEvent
2013-11-19 14:02:42 -05:00
392e224831 Fix build
Forgot to delete the line above it when cherry-picking... oops.
2013-11-19 14:01:18 -05:00
6867d44573 window: don't ignore resize button release event for move/resize actions
https://bugzilla.gnome.org/show_bug.cgi?id=710251
2013-11-19 13:55:17 -05:00
a841fff2ac screen: Laters are not GSources
This warns with the new GLib when we destroy the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=711731
2013-11-19 13:52:56 -05:00
26aa10a974 compositor: Clean up comment
So it seems that we were intentionally delaying the output window,
although I wonder why...
2013-11-19 13:52:45 -05:00
f6144082b1 compositor: Initialize the plugin manager after initializing the output window
Plugins like gnome-shell may want to grab the output window immediately
before bouncing back to the mainloop.
2013-11-19 13:52:13 -05:00
957513242c xrandr: use "hotplug_mode_update" property
Use the "hotplug_mode_update" connector property indicating that the
screen settings should be updated: get a new preferred mode on hotplug
events to handle dynamic guest resizing (where you resize the host
window and the guest resizes with it).

https://bugzilla.gnome.org/show_bug.cgi?id=711216
2013-11-19 13:50:15 -05:00
17fd25e216 doc: Fix file globs
Any files matching the previously used globs are no longer distributed,
breaking distcheck. Match the actual sources in compositor/, core/, meta/
and ui/ instead.
2013-11-19 13:48:40 -05:00
e91268a250 Add keyboard shortcut for Always on Top, bug 704831 2013-11-19 13:48:35 -05:00
82cb4e8267 display: Don't focus the no-focus-window when sending WM_TAKE_FOCUS to a globally active window
Clients like on-screen keyboards try not to take focus when the user clicks
on their window by setting the Input hint to false. However, due to GTK+ and
GDK bugs, the public API for setting the Input hint to false don't remove
WM_TAKE_FOCUS from WM_PROTOCOLS, unintentionally putting them into Globally
Active mode.

These clients also expect that since they don't want to take focus, they want
the focus to remain on the existing window. In this case, for clients like
on-screen keyboards, it's so they can send synthesized keyboard events to the
focused window.

https://bugzilla.gnome.org/show_bug.cgi?id=710296
2013-11-19 13:46:34 -05:00
68eb87cc58 build: Make sure built-sources are introspected as needed 2013-11-19 13:46:22 -05:00
f3e52d5b18 build: Do not ship generated source-files in tarball 2013-11-19 13:46:21 -05:00
2b2b2d3191 stack: Don't take a weak pointer
Since this is stored in an array full of data that will be copied
around, we can't rely on pointer addresses for every item in a stack
not changing.

I don't see any reason that we even have a weak pointer, either.
This code looks safe to me without it.
2013-11-19 13:10:45 -05:00
9461c612de wayland-surface: Only spew about set_buffer_scale if it's not 1
... to stop the GTK+ spam on my system.
2013-11-19 13:00:34 -05:00
f0280a8868 wayland-surface: Allow setting a NULL buffer to effectively unmap 2013-11-19 12:47:50 -05:00
c749f7b6fb Revert "ff"
This reverts commit 74462133ca.

Pushed by accident, if it wasn't obvious...
2013-11-19 11:22:49 -05:00
74462133ca ff 2013-11-18 21:35:30 -05:00
7c45d6594c MetaWindowActor: Use allocation changes signals for size changed signals
When a Wayland compositor, simply rely on the clutter actor allocation
changed signal to sync geometry and emit window actor size changed
signals.

Attaching a wl_buffer to a MetaShapedTexture will signal allocation
changed on the corresponding MetaSurfaceActor, which the MetaWindowActor
is listening to.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2013-11-18 21:19:01 -05:00
ea916b6c49 Introduce MetaSurfaceActor for drawing MetaWindowActor content
Instead of having MetaWindowActor only have one single MetaShapedTexture
as actor drawing its content, introduce a new abstract MetaSurfaceActor
that takes care of drawing.

This is one step in the direction to decouple MetaWaylandSurface with a
MetaWindow and MetaWindowActor (except for shell/xdg surfaces) in order
to finally support subsurfaces like features, or any feature where
window is not drawn using a single texture.

The first step, implemented in this patch, is to not have
MetaWindowActor work directly with a shaped texture. There are still
some cases where it simply gets the texture and goes on as before, but
this should be changed by either removing the need of going via
MetaWindowActor or by adding some generic interface to MetaSurfaceActor
that doesn't limit its functionality to one shaped texture.

There should be no visible difference nor after this patch, but
meta_window_actor_get_texture() and meta_surface_actor_get_texture()
should be deprecated when equivalent functionality has been introduced.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
2013-11-18 21:19:00 -05:00
a02d734243 window-actor: Move all buffer management and damage correction here
We want ShapedTexture to be a dumb actor that knows how to
pick/paint fairly easily, without any "platform knowledge", so to say...
2013-11-18 21:19:00 -05:00
735b736110 shaped-texture: Use the cogl helper methods for fetching shm_buffer contents
Rather than doing the set_region ourselves.
2013-11-18 21:19:00 -05:00
bbbb9ac53c display: Make handle_[x]event private 2013-11-18 21:19:00 -05:00
8dd97b4998 compositor: Remove outdated comment
XWayland no longer redirects windows by default.
2013-11-18 21:18:59 -05:00
73a9082062 cursor-tracker: Make ensure_wayland_cursor take a ref
This fixes a crash in the last commit because that's what I thought
this would do.

It also simplifies callers drastically...
2013-11-18 19:47:34 -05:00
4091f5493d cursor-tracker: Force the grab cursor on grab ops
This makes window moving have a 'window move' cursor, and similar.
2013-11-18 19:34:24 -05:00
d96b053c9d cursor-tracker: Use a sync methodology for the cursor image
Rather than have MetaWaylandSeat do all the state management itself,
put the split between the root cursor and the window cursor in the
cursor tracker itself. We'll expand this to add a "grab" cursor in
the next commit, allowing us to force a cursor on grab operations.
2013-11-18 19:25:47 -05:00
1f569bef76 Fix dragging on move/resize grabs
We need to use the grab_window for incoming events if we have an active grab.
2013-11-18 18:38:24 -05:00
1a88176cc0 keyboard: Fix surface focusing
Bad rebase...
2013-11-18 16:52:10 -05:00
662c9729bc trivial: window-actor: Fix formatting 2013-11-17 19:16:30 -05:00
56a0dd6b2c trivial: shaped-texture: Move set_base_texture to set_cogl_texture
A simple code cleanup.
2013-11-17 19:16:29 -05:00
9dc6028b3d trivial: shaped-texture: Fix documentation typo 2013-11-17 19:16:29 -05:00
932e913d88 wayland-surface: Fix formatting 2013-11-14 21:49:51 -05:00
b72315e27a wayland-surface: Support xdg_surface_resize as well 2013-11-14 21:48:39 -05:00
3c7cd1f38c wayland-surface: Use begin_grab_op for move grabs 2013-11-14 21:34:20 -05:00
1946c548bf Bump required Clutter version 2013-11-14 14:40:43 -05:00
cf181fe109 display: Adapt to new clutter event filter API 2013-11-14 14:34:53 -05:00
63b9110f93 wayland: Update internal wayland state unconditionally
Things like idle times and the cursor position need to be updated even
if there's a mutter grab in effect.

https://bugzilla.gnome.org/show_bug.cgi?id=712247
2013-11-13 21:55:05 +01:00
ae44bff0b1 display: Without a grab op let events go through clutter too
We want events to reach clutter no only when there a compositor modal
grab but also when no grab op is in effect.

https://bugzilla.gnome.org/show_bug.cgi?id=712247
2013-11-13 21:55:04 +01:00
23ba3e527f wayland: Support alternative focus modes like focus-follows-mouse
Use the existing code for MetaWindow focus-follows-mouse to support this.
2013-11-12 16:53:15 -05:00
08df9bf559 display: Use MetaWindow for auto-raise callbacks
This allows us to autoraise Wayland windows... well, except for the
XQueryPointer, but we'll replace that soon.
2013-11-12 16:53:15 -05:00
648639fffe display: Invoke Wayland from the Grand Central Station callback 2013-11-12 16:53:15 -05:00
6cc014a941 wayland: Move cursor tracker handling code to meta_wayland_seat_handle_event 2013-11-12 16:53:14 -05:00
b7b95123ed wayland: Drop raise on click too
We'll handle this through GCD as well.
2013-11-12 16:53:14 -05:00
153463790a wayland: Drop focus on click
The native raise-on-click works with Wayland clients through the standard
Grand Central Station event handling, with MetaWindow.
2013-11-12 16:53:14 -05:00
875bbec949 wayland: Drop old hack to synthesize motion events
mutter now uses Clutter events for the source of its drag support, so
we don't need to synthesize X11 events anymore.
2013-11-12 16:53:14 -05:00
666e5f1f98 keybindings: Port to Clutter 2013-11-12 16:53:14 -05:00
e6790038dd wayland: Use an event filter instead of the captured event signal
In order to see all Clutter events, Mutter was previously installing a
signal handler on the ‘captured-event’ signal on the stage and
additionally using a signal emission hook to cope with grabs. This
changes it to use the new clutter_event_add_filter API so that we can
avoid the signal emission hook hack.
2013-11-12 16:53:14 -05:00
e86c53230f display: Move the pointer event handling code to work in terms of Clutter events
There is now a meta_display_handle_event alongside the
meta_display_handle_xevent function which handles events in terms of
Clutter events instead of X events. A Clutter event filter is
registered so that all Clutter events will pass through this function.
The pointer event handling code from the X event version has been moved
into this new function and has been modified to use the details from
the Clutter event instead of the X event. This is a step towards
moving all of the event handling code over to use Clutter events.

Based-heavily-on-a-patch-by: Neil Roberts <neil@linux.intel.com>
2013-11-12 16:53:14 -05:00
4ea4658abf display: Split out other event handling as well
This vastly simplifies the code in event_callback and allows us to potentially
take more of this logic and punt it to Wayland-specific backends.
2013-11-12 16:53:14 -05:00
58f6ab0a27 display: Split out input event handling
This helps with git's diff code by moving all the giant indentation
changes, letting us know what's going on better when we move to
Clutter for event handling.
2013-11-12 16:53:14 -05:00
9c0cc664d1 display: Rename filter_out_event to bypass_gtk
This clarifies the intent of the variable and makes it match bypass_compositor
2013-11-12 16:53:14 -05:00
84d26e31f1 display: Move barrier event processing to barrier.c
This puts all the code that's easily ported to Clutter events in one giant
switch statement, as Clutter doesn't translate barrier events.
2013-11-12 16:53:14 -05:00
64a848fcb7 display: Add a quick out path to handle_xevent
This makes the code flow more like the scheme we usually use, and allows
us to flatten out the method somewhat.
2013-11-12 16:53:14 -05:00
429583ae8b display: Rename meta_display_handle_event to meta_display_handle_xevent
The plan is to make a new version of meta_display_handle_event that
will accept Clutter events instead of X events and then gradually move
over the events to the new function and finally remove the X version.
2013-11-12 16:53:14 -05:00
93ae868987 wayland: sync the keymap from X to wayland
When X clients change the keyboard map, the also update a property
on the root window. We can notice that and rebuild our data structures
with the new values, as well as inform the wayland clients.

This is a terrible hack, and it's not how we want to implement things
in 3.12, but it's enough to have the same keyboard layout in the
shell, in X clients and in wayland clients in 3.10, until we decide
on the fate of the keyboard g-s-d plugin.

https://bugzilla.gnome.org/show_bug.cgi?id=707446
2013-11-12 16:53:13 -05:00
72a900787f wayland: Send xdg_surface_focused_set / xdg_surface_focused_unset 2013-11-12 16:53:13 -05:00
7186841db0 wayland-surface: Remove initial_state
Just put everything in the double buffered state so it all
arrives at the same time; on commit.
2013-11-12 16:53:13 -05:00
ab080e3e6b Add support for xdg-shell
Replace our existing support for wl_shell with xdg_shell, the new proposal
for how Wayland surfaces should work.
2013-11-12 16:53:13 -05:00
ad84aef766 wayland-seat: Fix updating the grab serial
We shouldn't update the grab serial if we go from 2 buttons => 1.
2013-11-12 15:52:14 -05:00
7908eca579 protocol: Ship gtk-shell.xml 2013-11-08 17:03:10 -05:00
237d990dea mutter-wl: Support setting NULL surface regions.
According to the wayland spec (A.14.1.5. wl_surface::set_opaque_region),
setting a NULL opaque region is possible and should cause the pending
opaque region to be set to empty. This implements the required
behavoir.

Also fixes set_input_region, which suffered from an analogous bug.

Previously the weston-simple-egl demo client caused mutter-wayland to
crash with a segfault in meta_wayland_surface_set_opaque_region, with
this patch it works as intended.

https://bugzilla.gnome.org/show_bug.cgi?id=711518
2013-11-05 18:18:15 -05:00
192 changed files with 11545 additions and 15767 deletions

6
.gitignore vendored
View File

@ -48,7 +48,6 @@ po/*.pot
50-metacity-key.xml
libmutter-wayland.pc
mutter-wayland
mutter-launch
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
@ -77,12 +76,13 @@ src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-xrandr.[ch]
src/meta-dbus-idle-monitor.[ch]
src/meta-dbus-login1.[ch]
src/mutter-plugins.pc
src/wayland/gtk-shell-protocol.c
src/wayland/gtk-shell-client-protocol.h
src/wayland/gtk-shell-server-protocol.h
src/wayland/xdg-shell-protocol.c
src/wayland/xdg-shell-server-protocol.h
src/wayland/xserver-protocol.c
src/wayland/xserver-client-protocol.h
src/wayland/xserver-server-protocol.h
doc/reference/*.args
doc/reference/*.bak

41
COPYING
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
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
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

83
NEWS
View File

@ -1,3 +1,86 @@
3.11.91
=======
* Don't use keysym to match keybindings [Rui; #678001]
* Fix message tray icons showing up blank (again) [Adel; #725180]
* Improve keybinding lookups [Rui; #725588]
* Fix dynamic updates of titlebar style properties [Owen; #725751]
* Fix positioning of manually positioned windows [Owen; #724049]
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
#724969, #725216, #724402, #722266, #725338, #725525]
Contributors:
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Owen W. Taylor
3.11.90
=======
* Fix double-scaling on high DPI resolutions [Adel; #723931]
* Make tile previews a compositor effect [Stefano, Florian; #665758]
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257,
#724258, #720631, #724364, #724472]
Contributors:
Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah,
Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
3.11.5
======
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
* Add support for subsurfaces [Jonas; #705502]
* Expose MetaWindow:skip-taskbar property [Florian; #723307]
* Fix legacy tray icons showing up blank [Adel; #721596]
* Fix configuration of cloned monitors [Adel; #710610]
* Misc bug fixes and cleanups [Jasper, Adel, Marek, Jonas; #720631, #723468,
#720818, #723563, #723564]
Contributors:
Jonas Ådahl, Marek Ch, Adel Gadllah, Florian Müllner, Jasper St. Pierre
3.11.4
======
* Don't leave focus on windows that are being unmanaged [Owen; #711618]
* Reduce server grabs [Daniel Drake; #721345, #721709]
* Improve heuristic to determine display output name [Cosimo Cecchi; #721674]
* Atomically unmaximize both directions [Jasper; #722108]
* Misc bug fixes [Debarshi, Andika, Florian; #721517, #721674, #722347]
Contributors:
Cosimo Cecchi, Daniel Drake, Florian Müllner, Debarshi Ray, Jasper St. Pierre,
Andika Triwidada, Owen W. Taylor
3.11.3
======
* Fix focus issues with external OSKs[Jasper; #715030]
* Add a MetaCullable interface [Jasper; #714706]
* Fix window keybindings [Rui; #719724]
* Fix settings keyboard/pointer focus for new clients [Rui; #719725]
* Fix window group paint volume [Owen; #719669]
* Fix frame extents problems [Owen; #714707]
* Add shortcut to move windows between monitors [Florian; #671054]
* Fix problems with focus tracking [Owen; #720558]
* Misc. bug fixes and cleanups: [Rui, Colin, Lionel, Jasper, Owen; #712833,
#719557, #719695, #719833, #678989, #720417, #720630]
Contributors:
Lionel Landwerlin, Rui Matos, Alberto Milone, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor, Colin Walters
3.11.2
======
* Support setting a NULL opaque region [Andreas; #711518]
* Sync keymap from X to wayland [Giovanni; #707446]
* Implement support for subsurfaces [Jonas; #705502]
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
* Support "hotplug_mode_update" property [Marc-André; #711216]
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
* Fix position of attached modals for CSD windows [Giovanni, Owen; #707194]
* Misc. bug fixes [Rui, Jasper, Neil, Florian; #712247, #711731]
Contributors:
Giovanni Campagna, Andreas Heider, Lionel Landwerlin, Marc-André Lureau,
Rui Matos, Florian Müllner, Neil Roberts, Sindhu S, Jasper St. Pierre,
Rico Tzschichholz, Owen W. Taylor, Jonas Ådahl
3.11.1
======
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`

View File

@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [11])
m4_define([mutter_micro_version], [1])
m4_define([mutter_micro_version], [91])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -78,8 +78,8 @@ MUTTER_PC_MODULES="
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.15.94
cogl-1.0 >= 1.13.3
$CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1
upower-glib >= 0.99.0
gnome-desktop-3.0
"
@ -140,12 +140,6 @@ AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
saved_LIBS="$LIBS"
LIBS="$LIBS $MUTTER_LAUNCH"
AC_CHECK_FUNCS([sd_session_get_vt])
LIBS="$saved_LIBS"
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@ -212,16 +206,13 @@ fi
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
# We always build with wayland enabled
AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support])
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm"
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm libsystemd"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_EXISTS([xi >= 1.6.99.1],

View File

@ -49,8 +49,8 @@ FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/*.h
CFILE_GLOB=$(top_srcdir)/src/*.c
HFILE_GLOB=$(top_srcdir)/src/*/*.h
CFILE_GLOB=$(top_srcdir)/src/*/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h

View File

@ -96,8 +96,6 @@ meta_compositor_hide_window
meta_compositor_switch_workspace
meta_compositor_maximize_window
meta_compositor_unmaximize_window
meta_compositor_window_mapped
meta_compositor_window_unmapped
meta_compositor_sync_window_geometry
meta_compositor_set_updates_frozen
meta_compositor_queue_frame_drawn
@ -388,6 +386,23 @@ MetaWindowActorPrivate
meta_window_actor_get_type
</SECTION>
<SECTION>
<FILE>meta-cullable</FILE>
<TITLE>MetaCullable</TITLE>
MetaCullable
MetaCullableInterface
meta_cullable_cull_out
meta_cullable_reset_culling
meta_cullable_cull_out_children
meta_cullable_reset_culling_children
<SUBSECTION Standard>
META_TYPE_CULLABLE
META_CULLABLE
META_IS_CULLABLE
META_CULLABLE_GET_IFACE
meta_cullable_get_type
</SECTION>
<SECTION>
<FILE>prefs</FILE>
MetaPreference
@ -541,7 +556,10 @@ meta_window_is_override_redirect
meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_input_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect
meta_window_frame_rect_to_client_rect
meta_window_get_screen
meta_window_get_display
meta_window_get_xwindow

View File

@ -1 +1,7 @@
EXTRA_DIST = xserver.xml
NULL =
EXTRA_DIST = \
gtk-shell.xml \
xdg-shell.xml \
xserver.xml \
$(NULL)

475
protocol/xdg-shell.xml Normal file
View File

@ -0,0 +1,475 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="xdg_shell">
<copyright>
Copyright © 2008-2013 Kristian Høgsberg
Copyright © 2013 Rafael Antognolli
Copyright © 2013 Jasper St. Pierre
Copyright © 2010-2013 Intel Corporation
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="xdg_shell" version="1">
<description summary="create desktop-style surfaces">
This interface is implemented by servers that provide
desktop-style user interfaces.
It allows clients to associate a xdg_surface with
a basic surface.
</description>
<enum name="version">
<description summary="latest protocol version">
The 'current' member of this enum gives the version of the
protocol. Implementations can compare this to the version
they implement using static_assert to ensure the protocol and
implementation versions match.
</description>
<entry name="current" value="3" summary="Always the latest version"/>
</enum>
<request name="use_unstable_version">
<description summary="enable use of this unstable version">
Negotiate the unstable version of the interface. This
mechanism is in place to ensure client and server agree on the
unstable versions of the protocol that they speak or exit
cleanly if they don't agree. This request will go away once
the xdg-shell protocol is stable.
</description>
<arg name="version" type="int"/>
</request>
<request name="get_xdg_surface">
<description summary="create a shell surface from a surface">
Create a shell surface for an existing surface.
Only one shell or popup surface can be associated with a given
surface.
</description>
<arg name="id" type="new_id" interface="xdg_surface"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
<request name="get_xdg_popup">
<description summary="create a shell surface from a surface">
Create a popup surface for an existing surface.
Only one shell or popup surface can be associated with a given
surface.
</description>
<arg name="id" type="new_id" interface="xdg_popup"/>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="parent" type="object" interface="wl_surface"/>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="flags" type="uint"/>
</request>
<event name="ping">
<description summary="check if the client is alive">
The ping event asks the client if it's still alive. Pass the
serial specified in the event back to the compositor by sending
a "pong" request back with the specified serial.
Compositors can use this to determine if the client is still
alive. It's unspecified what will happen if the client doesn't
respond to the ping request, or in what timeframe. Clients should
try to respond in a reasonable amount of time.
</description>
<arg name="serial" type="uint" summary="pass this to the callback"/>
</event>
<request name="pong">
<description summary="respond to a ping event">
A client must respond to a ping event with a pong request or
the client may be deemed unresponsive.
</description>
<arg name="serial" type="uint" summary="serial of the ping event"/>
</request>
</interface>
<interface name="xdg_surface" version="1">
<description summary="desktop-style metadata interface">
An interface that may be implemented by a wl_surface, for
implementations that provide a desktop-style user interface.
It provides requests to treat surfaces like windows, allowing to set
properties like maximized, fullscreen, minimized, and to move and resize
them, and associate metadata like title and app id.
On the server side the object is automatically destroyed when
the related wl_surface is destroyed. On client side,
xdg_surface.destroy() must be called before destroying
the wl_surface object.
</description>
<request name="destroy" type="destructor">
<description summary="remove xdg_surface interface">
The xdg_surface interface is removed from the wl_surface object
that was turned into a xdg_surface with
xdg_shell.get_xdg_surface request. The xdg_surface properties,
like maximized and fullscreen, are lost. The wl_surface loses
its role as a xdg_surface. The wl_surface is unmapped.
</description>
</request>
<request name="set_transient_for">
<description summary="surface is a child of another surface">
Setting a surface as transient of another means that it is child
of another surface.
Child surfaces are stacked above their parents, and will be
unmapped if the parent is unmapped too. They should not appear
on task bars and alt+tab.
</description>
<arg name="parent" type="object" interface="wl_surface" allow-null="true"/>
</request>
<request name="set_margin">
<description summary="set the visible frame boundaries">
This tells the compositor what the visible size of the window
should be, so it can use it to determine what borders to use for
constrainment and alignment.
CSD often has invisible areas for decoration purposes, like drop
shadows. These "shadow" drawings need to be subtracted out of the
normal boundaries of the window when computing where to place
windows (e.g. to set this window so it's centered on top of another,
or to put it to the left or right of the screen.)
This value should change as little as possible at runtime, to
prevent flicker.
This value is also ignored when the window is maximized or
fullscreen, and assumed to be 0.
If never called, this value is assumed to be 0.
</description>
<arg name="left_margin" type="int"/>
<arg name="right_margin" type="int"/>
<arg name="top_margin" type="int"/>
<arg name="bottom_margin" type="int"/>
</request>
<request name="set_title">
<description summary="set surface title">
Set a short title for the surface.
This string may be used to identify the surface in a task bar,
window list, or other user interface elements provided by the
compositor.
The string must be encoded in UTF-8.
</description>
<arg name="title" type="string"/>
</request>
<request name="set_app_id">
<description summary="set surface class">
Set an id for the surface.
The app id identifies the general class of applications to which
the surface belongs.
It should be the ID that appears in the new desktop entry
specification, the interface name.
</description>
<arg name="app_id" type="string"/>
</request>
<enum name="surface_type">
<description summary="surface types">
Surface
</description>
<entry name="normal" value="0" summary="A normal window. This is the default type."/>
<entry name="modal_dialog" value="1" summary="A modal dialog."/>
</enum>
<request name="set_surface_type">
<description summary="set the surface type">
Sets the type of the surface. These are high-level "roles" of
surfaces designed to give the compositor more heuristics about
how to place and manage the window.
</description>
<arg name="surface_type" type="uint" summary="a surface type from surface_type"/>
</request>
<request name="show_window_menu">
<description summary="show the window menu">
Clients implementing client-side decorations might want to show
a context menu when right-clicking on the decorations, giving the
user a menu that they can use to maximize or minimize the window.
The seat passed must have either pointer or keyboard focus to pop
up the window menu for a surface.
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/>
<arg name="serial" type="uint" summary="serial of the event to pop up the window for"/>
</request>
<request name="move">
<description summary="start an interactive move">
Start a pointer-driven move of the surface.
This request must be used in response to a button press event.
The server may ignore move requests depending on the state of
the surface (e.g. fullscreen or maximized).
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
</request>
<enum name="resize_edge">
<description summary="edge values for resizing">
These values are used to indicate which edge of a surface
is being dragged in a resize operation. The server may
use this information to adapt its behavior, e.g. choose
an appropriate cursor image.
</description>
<entry name="none" value="0"/>
<entry name="top" value="1"/>
<entry name="bottom" value="2"/>
<entry name="left" value="4"/>
<entry name="top_left" value="5"/>
<entry name="bottom_left" value="6"/>
<entry name="right" value="8"/>
<entry name="top_right" value="9"/>
<entry name="bottom_right" value="10"/>
</enum>
<request name="resize">
<description summary="start an interactive resize">
Start a pointer-driven resizing of the surface.
This request must be used in response to a button press event.
The server may ignore resize requests depending on the state of
the surface (e.g. fullscreen or maximized).
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
<arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
</request>
<event name="configure">
<description summary="suggest resize">
The configure event asks the client to resize its surface.
The size is a hint, in the sense that the client is free to
ignore it if it doesn't resize, pick a smaller size (to
satisfy aspect ratio or resize in steps of NxM pixels).
The client is free to dismiss all but the last configure
event it received.
The width and height arguments specify the size of the window
in surface local coordinates.
</description>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</event>
<request name="set_output">
<description summary="set the default output used by this surface">
Set the default output used by this surface when it is first mapped.
If this value is NULL (default), it's up to the compositor to choose
which display will be used to map this surface.
When fullscreen or maximized state are set on this surface, and it
wasn't mapped yet, the output set with this method will be used.
Otherwise, the output where the surface is currently mapped will be
used.
</description>
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
</request>
<enum name="state">
<description summary="types of state on the surface">
The different state values used on the surface. This is designed for
state values like maximized, fullscreen. It is paired with the
request_change_state event to ensure that both the client and the
compositor setting the state can be synchronized.
States set in this way are double-buffered. They will get applied on
the next commit.
Desktop environments may extend this enum by taking up a range of
values and documenting the range they chose in this description.
They are not required to document the values for the range that they
chose. Ideally, any good extensions from a desktop environment should
make its way into standardization into this enum.
The current reserved ranges are:
0x0000 - 0x0FFF: xdg-shell core values, documented below.
0x1000 - 0x1FFF: GNOME
</description>
<entry name="maximized" value="1" summary="the surface is maximized">
A non-zero value indicates the surface is maximized. Otherwise,
the surface is unmaximized.
</entry>
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
A non-zero value indicates the surface is fullscreen. Otherwise,
the surface is not fullscreen.
</entry>
</enum>
<request name="request_change_state">
<description summary="client requests to change a surface's state">
This asks the compositor to change the state. If the compositor wants
to change the state, it will send a change_state event with the same
state_type, value, and serial, and the event flow continues as if it
it was initiated by the compositor.
If the compositor does not want to change the state, it will send a
change_state to the client with the old value of the state.
</description>
<arg name="state_type" type="uint" summary="the state to set"/>
<arg name="value" type="uint" summary="the value to change the state to"/>
<arg name="serial" type="uint" summary="an event serial">
This serial is so the client can know which change_state event corresponds
to which request_change_state request it sent out.
</arg>
</request>
<event name="change_state">
<description summary="compositor wants to change a surface's state">
This event tells the client to change a surface's state. The client
should respond with an ack_change_state request to the compositor to
guarantee that the compositor knows that the client has seen it.
</description>
<arg name="state_type" type="uint" summary="the state to set"/>
<arg name="value" type="uint" summary="the value to change the state to"/>
<arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
</event>
<request name="ack_change_state">
<description summary="ack a change_state event">
When a change_state event is received, a client should then ack it
using the ack_change_state request to ensure that the compositor
knows the client has seen the event.
By this point, the state is confirmed, and the next attach should
contain the buffer drawn for the new state value.
The values here need to be the same as the values in the cooresponding
change_state event.
</description>
<arg name="state_type" type="uint" summary="the state to set"/>
<arg name="value" type="uint" summary="the value to change the state to"/>
<arg name="serial" type="uint" summary="a serial to pass to change_state"/>
</request>
<request name="set_minimized">
<description summary="minimize the surface">
Minimize the surface.
</description>
</request>
<event name="activated">
<description summary="surface was activated">
The activated_set event is sent when this surface has been
activated, which means that the surface has user attention.
Window decorations should be updated accordingly. You should
not use this event for anything but the style of decorations
you display, use wl_keyboard.enter and wl_keyboard.leave for
determining keyboard focus.
</description>
</event>
<event name="deactivated">
<description summary="surface was deactivated">
The deactivate event is sent when this surface has been
deactivated, which means that the surface lost user attention.
Window decorations should be updated accordingly. You should
not use this event for anything but the style of decorations
you display, use wl_keyboard.enter and wl_keyboard.leave for
determining keyboard focus.
</description>
</event>
<event name="delete">
<description summary="surface wants to be closed">
The delete event is sent by the compositor when the user
wants the surface to be closed. This should be equivalent to
the user clicking the close button in client-side decorations,
if your application has any...
This is only a request that the user intends to close your
window. The client may choose to ignore this request, or show
a dialog to ask the user to save their data...
</description>
</event>
</interface>
<interface name="xdg_popup" version="1">
<description summary="desktop-style metadata interface">
An interface that may be implemented by a wl_surface, for
implementations that provide a desktop-style popups/menus. A popup
surface is a transient surface with an added pointer grab.
An existing implicit grab will be changed to owner-events mode,
and the popup grab will continue after the implicit grab ends
(i.e. releasing the mouse button does not cause the popup to be
unmapped).
The popup grab continues until the window is destroyed or a mouse
button is pressed in any other clients window. A click in any of
the clients surfaces is reported as normal, however, clicks in
other clients surfaces will be discarded and trigger the callback.
The x and y arguments specify the locations of the upper left
corner of the surface relative to the upper left corner of the
parent surface, in surface local coordinates.
xdg_popup surfaces are always transient for another surface.
</description>
<request name="destroy" type="destructor">
<description summary="remove xdg_surface interface">
The xdg_surface interface is removed from the wl_surface object
that was turned into a xdg_surface with
xdg_shell.get_xdg_surface request. The xdg_surface properties,
like maximized and fullscreen, are lost. The wl_surface loses
its role as a xdg_surface. The wl_surface is unmapped.
</description>
</request>
<event name="popup_done">
<description summary="popup interaction is done">
The popup_done event is sent out when a popup grab is broken,
that is, when the users clicks a surface that doesn't belong
to the client owning the popup surface.
</description>
<arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
</event>
</interface>
</protocol>

View File

@ -29,6 +29,18 @@
<KeyListEntry name="move-to-workspace-down"
_description="Move window one workspace down" />
<KeyListEntry name="move-to-monitor-left"
_description="Move window one monitor to the left" />
<KeyListEntry name="move-to-monitor-right"
_description="Move window one monitor to the right" />
<KeyListEntry name="move-to-monitor-up"
_description="Move window one monitor up" />
<KeyListEntry name="move-to-monitor-down"
_description="Move window one monitor down" />
<KeyListEntry name="switch-applications"
_description="Switch applications"/>

View File

@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter-wayland.la
SUBDIRS=compositor/plugins
INCLUDES= \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
@ -38,14 +39,15 @@ INCLUDES += \
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_xrandr_built_sources) \
$(dbus_login1_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
wayland/gtk-shell-protocol.c \
wayland/gtk-shell-server-protocol.h \
wayland/gtk-shell-client-protocol.h \
wayland/xdg-shell-protocol.c \
wayland/xdg-shell-server-protocol.h \
wayland/xserver-protocol.c \
wayland/xserver-server-protocol.h \
wayland/xserver-client-protocol.h
wayland/xserver-server-protocol.h
libmutter_wayland_la_SOURCES = \
core/async-getprop.c \
@ -67,7 +69,8 @@ libmutter_wayland_la_SOURCES = \
compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \
compositor/meta-background-group.c \
compositor/meta-background-group-private.h \
compositor/meta-cullable.c \
compositor/meta-cullable.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
@ -77,6 +80,12 @@ libmutter_wayland_la_SOURCES = \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture-private.h \
compositor/meta-surface-actor.c \
compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@ -105,8 +114,6 @@ libmutter_wayland_la_SOURCES = \
core/display.c \
core/display-private.h \
meta/display.h \
ui/draw-workspace.c \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/edid-parse.c \
@ -157,6 +164,8 @@ libmutter_wayland_la_SOURCES = \
core/util-private.h \
core/window-props.c \
core/window-props.h \
core/window-x11.c \
core/window-x11.h \
core/window.c \
core/window-private.h \
meta/window.h \
@ -169,25 +178,15 @@ libmutter_wayland_la_SOURCES = \
ui/ui.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
ui/menu.h \
ui/metaaccellabel.c \
ui/metaaccellabel.h \
ui/resizepopup.c \
ui/resizepopup.h \
ui/tabpopup.c \
ui/tabpopup.h \
ui/tile-preview.c \
ui/tile-preview.h \
ui/theme-parser.c \
ui/theme.c \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
$(mutter_built_sources)
libmutter_wayland_la_SOURCES += \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
@ -205,8 +204,11 @@ libmutter_wayland_la_SOURCES += \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \
wayland/meta-weston-launch.c \
wayland/meta-weston-launch.h
wayland/meta-login1.c \
wayland/meta-login1.h
nodist_libmutter_wayland_la_SOURCES = \
$(mutter_built_sources)
libmutter_wayland_la_LDFLAGS = -no-undefined
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
@ -258,17 +260,6 @@ bin_PROGRAMS=mutter-wayland
mutter_wayland_SOURCES = core/mutter.c
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
bin_PROGRAMS+=mutter-launch
mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
install-exec-hook:
-chown root $(DESTDIR)$(bindir)/mutter-launch
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@ -297,7 +288,7 @@ Meta-$(api_version).gir: libmutter-wayland.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_wayland_la_SOURCES))
$(filter %.c,$(libmutter_wayland_la_SOURCES) $(nodist_libmutter_wayland_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
endif
@ -404,12 +395,18 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
--c-generate-object-manager \
$(srcdir)/idle-monitor.xml
dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h
$(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.freedesktop.login1 \
--c-namespace Login1 \
--generate-c-code meta-dbus-login1 \
$(srcdir)/org.freedesktop.login1.xml
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-utils.h"
@ -95,8 +93,10 @@ meta_actor_vertices_are_untransformed (ClutterVertex *verts,
v3x != v1x || v3y != v2y)
return FALSE;
*x_origin = x;
*y_origin = y;
if (x_origin)
*x_origin = x;
if (y_origin)
*y_origin = y;
return TRUE;
}

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_CLUTTER_UTILS_H__

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <clutter/clutter.h>

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_COGL_UTILS_H__

View File

@ -17,8 +17,6 @@ struct _MetaCompositor
{
MetaDisplay *display;
Atom atom_x_root_pixmap;
Atom atom_net_wm_window_opacity;
guint repaint_func_id;
ClutterActor *shadow_src;
@ -48,11 +46,8 @@ struct _MetaCompScreen
CoglFrameClosure *frame_closure;
/* Used for unredirecting fullscreen windows */
guint disable_unredirect_count;
MetaWindowActor *unredirected_window;
/* Before we create the output window */
XserverRegion pending_input_region;
guint disable_unredirect_count;
MetaWindow *unredirected_window;
gint switch_workspace_in_progress;

View File

@ -42,15 +42,6 @@
* the call, so it may be necessary to readjust the display based on the
* old_rect to start the animation.
*
* meta_compositor_window_mapped() and meta_compositor_window_unmapped() are
* notifications when the toplevel window (frame or client window) is mapped or
* unmapped. That is, when the result of meta_window_toplevel_is_mapped()
* changes. The main use of this is to drop resources when a window is unmapped.
* A window will always be mapped before meta_compositor_show_window()
* is called and will not be unmapped until after meta_compositor_hide_window()
* is called. If the live_hidden_windows preference is set, windows will never
* be unmapped.
*
* # Containers #
*
* There's two containers in the stage that are used to place window actors, here
@ -85,6 +76,7 @@
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "util-private.h"
#include "frame.h"
#include "meta-wayland-private.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-keyboard.h"
@ -179,31 +171,6 @@ process_damage (MetaCompositor *compositor,
meta_window_actor_process_x11_damage (window_actor, event);
}
static void
process_property_notify (MetaCompositor *compositor,
XPropertyEvent *event,
MetaWindow *window)
{
MetaWindowActor *window_actor;
if (window == NULL)
return;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
/* Check for the opacity changing */
if (event->atom == compositor->atom_net_wm_window_opacity)
{
meta_window_actor_update_opacity (window_actor);
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
return;
}
DEBUG_TRACE ("process_property_notify: unknown\n");
}
static Window
get_output_window (MetaScreen *screen)
{
@ -308,25 +275,6 @@ meta_get_window_actors (MetaScreen *screen)
return info->windows;
}
static void
do_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
/* It's generally a good heuristic that when a crossing event is generated because
* we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
* it's not the user doing something, it's the environment changing under the user.
*/
meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
}
void
meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
@ -338,29 +286,19 @@ meta_set_stage_input_region (MetaScreen *screen,
*/
if (!meta_is_wayland_compositor ())
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
if (info->stage && info->output)
{
do_set_stage_input_region (screen, region);
}
else
{
/* Reset info->pending_input_region if one existed before and set the new
* one to use it later. */
if (info->pending_input_region)
{
XFixesDestroyRegion (xdpy, info->pending_input_region);
info->pending_input_region = None;
}
if (region != None)
{
info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
XFixesCopyRegion (xdpy, info->pending_input_region, region);
}
}
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
/* It's generally a good heuristic that when a crossing event is generated because
* we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
* it's not the user doing something, it's the environment changing under the user.
*/
meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
}
}
@ -392,39 +330,36 @@ meta_focus_stage_window (MetaScreen *screen,
if (!stage)
return;
if (!meta_is_wayland_compositor ())
{
window = clutter_x11_get_stage_window (stage);
window = clutter_x11_get_stage_window (stage);
if (window == None)
return;
if (window == None)
return;
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
window,
timestamp);
}
else
{
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
None,
timestamp);
}
meta_display_set_input_focus_xwindow (screen->display,
screen,
window,
timestamp);
}
gboolean
meta_stage_is_focused (MetaScreen *screen)
{
ClutterStage *stage;
Window window;
if (meta_is_wayland_compositor ())
return TRUE;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
return (screen->display->focus_type == META_FOCUS_STAGE);
window = clutter_x11_get_stage_window (stage);
if (window == None)
return FALSE;
return (screen->display->focus_xwindow == window);
}
static gboolean
@ -501,45 +436,6 @@ begin_modal_x11 (MetaScreen *screen,
return FALSE;
}
static gboolean
begin_modal_wayland (MetaScreen *screen,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
{
MetaWaylandCompositor *compositor;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
compositor = meta_wayland_compositor_get_default ();
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
{
if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
goto fail;
pointer_grabbed = TRUE;
}
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
{
if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard,
timestamp))
goto fail;
keyboard_grabbed = TRUE;
}
return TRUE;
fail:
if (pointer_grabbed)
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
if (keyboard_grabbed)
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard, timestamp);
return FALSE;
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
@ -558,7 +454,7 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
return FALSE;
if (meta_is_wayland_compositor ())
ok = begin_modal_wayland (screen, plugin, options, timestamp);
ok = TRUE;
else
ok = begin_modal_x11 (screen, plugin, options, timestamp);
if (!ok)
@ -586,15 +482,7 @@ meta_end_modal_for_plugin (MetaScreen *screen,
g_return_if_fail (compositor->modal_plugin == plugin);
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard,
timestamp);
}
else
if (!meta_is_wayland_compositor ())
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
@ -637,6 +525,9 @@ after_stage_paint (ClutterStage *stage,
for (l = info->windows; l; l = l->next)
meta_window_actor_post_paint (l->data);
if (meta_is_wayland_compositor ())
meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
}
static void
@ -650,11 +541,6 @@ redirect_windows (MetaCompositor *compositor,
guint n_retries;
guint max_retries;
/* If we're running with wayland, connected to a headless xwayland
* server then all the windows are implicitly redirected offscreen
* already and it would generate an error to try and explicitly
* redirect them via XCompositeRedirectSubwindows() */
if (meta_get_replace_current_wm ())
max_retries = 5;
else
@ -704,21 +590,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
return;
info = g_new0 (MetaCompScreen, 1);
/*
* We use an empty input region for Clutter as a default because that allows
* the user to interact with all the windows displayed on the screen.
* We have to initialize info->pending_input_region to an empty region explicitly,
* because None value is used to mean that the whole screen is an input region.
*/
if (!meta_is_wayland_compositor ())
info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
else
{
/* Stage input region trickery isn't needed when we're running as a
* wayland compositor. */
info->pending_input_region = None;
}
info->screen = screen;
meta_screen_set_compositor_data (screen, info);
@ -792,8 +663,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
info->plugin_mgr = meta_plugin_manager_new (screen);
if (meta_is_wayland_compositor ())
{
/* NB: When running as a wayland compositor we don't need an X
@ -803,16 +672,11 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
}
else
{
/*
* Delay the creation of the overlay window as long as we can, to avoid
* blanking out the screen. This means that during the plugin loading, the
* overlay window is not accessible; if the plugin needs to access it
* directly, it should hook into the "show" signal on stage, and do
* its stuff there.
*/
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
meta_empty_stage_input_region (screen);
/* Make sure there isn't any left-over output shape on the
* overlay window by setting the whole screen to be an
* output region.
@ -823,20 +687,15 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
do_set_stage_input_region (screen, info->pending_input_region);
if (info->pending_input_region != None)
{
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
redirect_windows (compositor, screen);
}
redirect_windows (compositor, screen);
info->plugin_mgr = meta_plugin_manager_new (screen);
}
void
@ -876,7 +735,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
int width, height;
MetaRectangle rect;
meta_window_get_outer_rect (metaWindow, &rect);
meta_window_get_frame_rect (metaWindow, &rect);
window_bounds.x = rect.x;
window_bounds.y = rect.y;
@ -897,6 +756,30 @@ meta_shape_cow_for_window (MetaScreen *screen,
}
}
static void
set_unredirected_window (MetaCompScreen *info,
MetaWindow *window)
{
if (info->unredirected_window == window)
return;
if (info->unredirected_window != NULL)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (info->unredirected_window));
meta_window_actor_set_unredirected (window_actor, FALSE);
}
info->unredirected_window = window;
if (info->unredirected_window != NULL)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (info->unredirected_window));
meta_window_actor_set_unredirected (window_actor, TRUE);
}
meta_shape_cow_for_window (info->screen, info->unredirected_window);
}
void
meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window)
@ -925,19 +808,11 @@ meta_compositor_remove_window (MetaCompositor *compositor,
if (!window_actor)
return;
if (!meta_is_wayland_compositor ())
{
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
if (window_actor == info->unredirected_window)
{
meta_window_actor_set_redirected (window_actor, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
info->unredirected_window = NULL;
}
}
if (info->unredirected_window == window)
set_unredirected_window (info, NULL);
meta_window_actor_destroy (window_actor);
}
@ -1007,23 +882,91 @@ meta_compositor_window_shape_changed (MetaCompositor *compositor,
meta_window_actor_update_shape (window_actor);
}
void
meta_compositor_window_opacity_changed (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
meta_window_actor_update_opacity (window_actor);
}
void
meta_compositor_window_surface_changed (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
meta_window_actor_update_surface (window_actor);
}
static gboolean
grab_op_is_clicking (MetaGrabOp grab_op)
{
switch (grab_op)
{
case META_GRAB_OP_CLICKING_MINIMIZE:
case META_GRAB_OP_CLICKING_MAXIMIZE:
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
case META_GRAB_OP_CLICKING_DELETE:
case META_GRAB_OP_CLICKING_MENU:
case META_GRAB_OP_CLICKING_SHADE:
case META_GRAB_OP_CLICKING_UNSHADE:
case META_GRAB_OP_CLICKING_ABOVE:
case META_GRAB_OP_CLICKING_UNABOVE:
case META_GRAB_OP_CLICKING_STICK:
case META_GRAB_OP_CLICKING_UNSTICK:
return TRUE;
default:
return FALSE;
}
}
static gboolean
event_is_passive_button_grab (MetaDisplay *display,
XIDeviceEvent *device_event)
{
/* see display.c for which events are passive button
grabs (meta_display_grab_window_buttons() and
meta_display_handle_events())
we need to filter them here because normally they
would be sent to gtk+ (they are on gtk+ frame xwindow),
but we want to redirect them to clutter
*/
if (device_event->evtype != XI_ButtonPress)
return FALSE;
if (display->window_grab_modifiers == 0)
return FALSE;
if ((device_event->mods.effective & display->window_grab_modifiers) !=
display->window_grab_modifiers)
return FALSE;
return device_event->detail < 4;
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
* to the a stage that isn't its X window.
*
* When a user clicks on what she thinks is the wallpaper, she
* is actually clicking on the guard window, which is an entirely
* separate top-level override-redirect window in the hierarchy.
* We want to recieve events on this guard window so that users
* can right-click on the background actor. We do this by telling
* Clutter a little white lie, by transforming clicks on the guard
* window to become clicks on the stage window, allowing Clutter
* to process the event normally.
* When running as an X window manager, we need to respond to
* events from lots of windows. Trick Clutter into translating
* these events by pretending we got an event on the stage window.
*/
static void
maybe_spoof_guard_window_event_as_stage_event (MetaCompScreen *info,
XEvent *event)
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
MetaWindow *window,
XEvent *event)
{
MetaDisplay *display = meta_screen_get_display (info->screen);
@ -1031,21 +974,30 @@ maybe_spoof_guard_window_event_as_stage_event (MetaCompScreen *info,
event->xcookie.extension == display->xinput_opcode)
{
XIEvent *input_event = (XIEvent *) event->xcookie.data;
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
/* Only care about pointer events for now. */
switch (input_event->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
{
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
if (device_event->event == info->screen->guard_window)
{
Window xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
device_event->event = xwin;
}
}
/* If this is a window frame, and we think GTK+ needs to handle the event,
let GTK+ handle it without mangling */
if (window && window->frame && device_event->event == window->frame->xwindow &&
(grab_op_is_clicking (display->grab_op) ||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
break;
case XI_KeyPress:
case XI_KeyRelease:
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
* it as-is without mangling. */
if (meta_ui_window_is_widget (info->screen->ui, device_event->event))
break;
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
break;
default:
break;
@ -1065,6 +1017,12 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
MetaDisplay *display = compositor->display;
MetaScreen *screen = display->screens->data;
MetaCompScreen *info;
info = meta_screen_get_compositor_data (screen);
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
{
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
@ -1074,68 +1032,29 @@ meta_compositor_process_event (MetaCompositor *compositor,
return TRUE;
}
if (window)
if (!meta_is_wayland_compositor ())
maybe_spoof_event_as_stage_event (info, window, event);
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
{
MetaCompScreen *info;
MetaScreen *screen;
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
{
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
return TRUE;
}
}
else
{
GSList *l;
l = meta_display_get_screens (compositor->display);
while (l)
{
MetaScreen *screen = l->data;
MetaCompScreen *info;
info = meta_screen_get_compositor_data (screen);
maybe_spoof_guard_window_event_as_stage_event (info, event);
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
{
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
return TRUE;
}
l = l->next;
}
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
return TRUE;
}
switch (event->type)
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{
case PropertyNotify:
process_property_notify (compositor, (XPropertyEvent *) event, window);
break;
default:
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
*/
if (window == NULL)
{
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
*/
if (window == NULL)
{
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
break;
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
/* Clutter needs to know about MapNotify events otherwise it will
@ -1435,30 +1354,6 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
sync_actor_stacking (info);
}
void
meta_compositor_window_mapped (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_window_mapped\n");
if (!window_actor)
return;
meta_window_actor_mapped (window_actor);
}
void
meta_compositor_window_unmapped (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_window_unmapped\n");
if (!window_actor)
return;
meta_window_actor_unmapped (window_actor);
}
void
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
@ -1566,7 +1461,6 @@ pre_paint_windows (MetaCompScreen *info)
{
GList *l;
MetaWindowActor *top_window;
MetaWindowActor *expected_unredirected_window = NULL;
if (info->onscreen == NULL)
{
@ -1580,33 +1474,13 @@ pre_paint_windows (MetaCompScreen *info)
if (info->windows == NULL)
return;
if (!meta_is_wayland_compositor ())
{
top_window = g_list_last (info->windows)->data;
top_window = g_list_last (info->windows)->data;
if (meta_window_actor_should_unredirect (top_window) &&
info->disable_unredirect_count == 0)
expected_unredirected_window = top_window;
if (info->unredirected_window != expected_unredirected_window)
{
if (info->unredirected_window != NULL)
{
meta_window_actor_set_redirected (info->unredirected_window, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
}
if (expected_unredirected_window != NULL)
{
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
meta_window_actor_get_meta_window (top_window));
meta_window_actor_set_redirected (top_window, FALSE);
}
info->unredirected_window = expected_unredirected_window;
}
}
if (meta_window_actor_should_unredirect (top_window) &&
info->disable_unredirect_count == 0)
set_unredirected_window (info, meta_window_actor_get_meta_window (top_window));
else
set_unredirected_window (info, NULL);
for (l = info->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data);
@ -1660,13 +1534,7 @@ on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor *
meta_compositor_new (MetaDisplay *display)
{
char *atom_names[] = {
"_XROOTPMAP_ID",
"_NET_WM_WINDOW_OPACITY",
};
Atom atoms[G_N_ELEMENTS(atom_names)];
MetaCompositor *compositor;
Display *xdisplay = meta_display_get_xdisplay (display);
if (!composite_at_least_version (display, 0, 3))
return NULL;
@ -1678,18 +1546,11 @@ meta_compositor_new (MetaDisplay *display)
if (g_getenv("META_DISABLE_MIPMAPS"))
compositor->no_mipmaps = TRUE;
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
g_signal_connect (meta_shadow_factory_get_default (),
"changed",
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->atom_x_root_pixmap = atoms[0];
compositor->atom_net_wm_window_opacity = atoms[1];
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);
@ -1834,3 +1695,43 @@ meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
else
return monotonic_time + compositor->server_time_offset;
}
void
meta_compositor_show_tile_preview (MetaCompositor *compositor,
MetaScreen *screen,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info->plugin_mgr)
return;
meta_plugin_manager_show_tile_preview (info->plugin_mgr,
window, tile_rect, tile_monitor_number);
}
void
meta_compositor_hide_tile_preview (MetaCompositor *compositor,
MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info->plugin_mgr)
return;
meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
}
void
meta_compositor_show_window_menu (MetaCompositor *compositor,
MetaWindow *window)
{
MetaCompScreen *info = meta_screen_get_compositor_data (window->screen);
if (!info->plugin_mgr)
return;
meta_plugin_manager_show_window_menu (info->plugin_mgr, window);
}

View File

@ -6,9 +6,6 @@
#include <meta/screen.h>
#include <meta/meta-background-actor.h>
void meta_background_actor_set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region);
cairo_region_t *meta_background_actor_get_clip_region (MetaBackgroundActor *self);
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Portions adapted from gnome-shell/src/shell-global.c
*/
@ -41,20 +39,35 @@
#include <meta/errors.h>
#include <meta/meta-background.h>
#include "meta-background-actor-private.h"
#include "meta-cullable.h"
struct _MetaBackgroundActorPrivate
{
cairo_region_t *clip_region;
};
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region)
{
MetaBackgroundActorPrivate *priv = self->priv;
g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
}
static void
meta_background_actor_dispose (GObject *object)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
meta_background_actor_set_clip_region (self, NULL);
set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
}
@ -104,26 +117,6 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
*natural_height_p = height;
}
static gboolean
meta_background_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
ClutterContent *content;
gfloat width, height;
content = clutter_actor_get_content (actor);
if (!content)
return FALSE;
clutter_content_get_preferred_size (content, &width, &height);
clutter_paint_volume_set_width (volume, width);
clutter_paint_volume_set_height (volume, height);
return TRUE;
}
static void
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
{
@ -136,7 +129,6 @@ meta_background_actor_class_init (MetaBackgroundActorClass *klass)
actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
}
static void
@ -166,31 +158,27 @@ meta_background_actor_new (void)
return CLUTTER_ACTOR (self);
}
/**
* meta_background_actor_set_clip_region:
* @self: a #MetaBackgroundActor
* @clip_region: (allow-none): the area of the actor (in allocate-relative
* coordinates) that is visible.
*
* Sets the area of the background that is unobscured by overlapping windows.
* This is used to optimize and only paint the visible portions.
*/
void
meta_background_actor_set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region)
static void
meta_background_actor_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
MetaBackgroundActorPrivate *priv;
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
set_clip_region (self, clip_region);
}
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
static void
meta_background_actor_reset_culling (MetaCullable *cullable)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
set_clip_region (self, NULL);
}
priv = self->priv;
g_clear_pointer (&priv->clip_region,
(GDestroyNotify)
cairo_region_destroy);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_background_actor_cull_out;
iface->reset_culling = meta_background_actor_reset_culling;
}
/**

View File

@ -1,11 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_BACKGROUND_GROUP_PRIVATE_H
#define META_BACKGROUND_GROUP_PRIVATE_H
#include <meta/screen.h>
#include <meta/meta-background-group.h>
void meta_background_group_set_clip_region (MetaBackgroundGroup *self,
cairo_region_t *visible_region);
#endif /* META_BACKGROUND_GROUP_PRIVATE_H */

View File

@ -16,87 +16,43 @@
#include <config.h>
#include "compositor-private.h"
#include "clutter-utils.h"
#include "meta-background-actor-private.h"
#include "meta-background-group-private.h"
#include <meta/meta-background-group.h>
#include "meta-cullable.h"
G_DEFINE_TYPE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
struct _MetaBackgroundGroupPrivate
{
gpointer dummy;
};
static void
meta_background_group_dispose (GObject *object)
{
G_OBJECT_CLASS (meta_background_group_parent_class)->dispose (object);
}
static gboolean
meta_background_group_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
}
G_DEFINE_TYPE_WITH_CODE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
meta_background_group_class_init (MetaBackgroundGroupClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
}
actor_class->get_paint_volume = meta_background_group_get_paint_volume;
object_class->dispose = meta_background_group_dispose;
static void
meta_background_group_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
g_type_class_add_private (klass, sizeof (MetaBackgroundGroupPrivate));
static void
meta_background_group_reset_culling (MetaCullable *cullable)
{
meta_cullable_reset_culling_children (cullable);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_background_group_cull_out;
iface->reset_culling = meta_background_group_reset_culling;
}
static void
meta_background_group_init (MetaBackgroundGroup *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_BACKGROUND_GROUP,
MetaBackgroundGroupPrivate);
}
/**
* meta_background_group_set_clip_region:
* @self: a #MetaBackgroundGroup
* @region: (allow-none): the parts of the background to paint
*
* Sets the area of the backgrounds that is unobscured by overlapping windows.
* This is used to optimize and only paint the visible portions.
*/
void
meta_background_group_set_clip_region (MetaBackgroundGroup *self,
cairo_region_t *region)
{
GList *children, *l;
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
for (l = children; l; l = l->next)
{
ClutterActor *actor = l->data;
if (META_IS_BACKGROUND_ACTOR (actor))
{
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (actor), region);
}
else if (META_IS_BACKGROUND_GROUP (actor))
{
int x, y;
if (!meta_actor_is_untransformed (actor, &x, &y))
continue;
cairo_region_translate (region, -x, -y);
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (actor), region);
cairo_region_translate (region, x, y);
}
}
g_list_free (children);
}
ClutterActor *

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**

View File

@ -0,0 +1,201 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Ray Strode <rstrode@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-cullable.h"
#include "clutter-utils.h"
G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR);
/**
* SECTION:meta-cullable
* @title: MetaCullable
* @short_description: CPU culling operations for efficient drawing
*
* When we are painting a stack of 5-10 large actors, the standard
* bottom-to-top method of drawing every actor results in a tremendous
* amount of overdraw. If these actors are painting textures like
* windows, it can easily max out the available memory bandwidth on a
* low-end graphics chipset. It's even worse if window textures are
* being accessed over the AGP bus.
*
* #MetaCullable is our solution. The basic technique applied here is to
* do a pre-pass before painting where we walk each actor from top to bottom
* and ask each actor to "cull itself out". We pass in a region it can copy
* to clip its drawing to, and the actor can subtract its fully opaque pixels
* so that actors underneath know not to draw there as well.
*/
/**
* meta_cullable_cull_out_children:
* @cullable: The #MetaCullable
* @unobscured_region: The unobscured region, as passed into cull_out()
* @clip_region: The clip region, as passed into cull_out()
*
* This is a helper method for actors that want to recurse over their
* child actors, and cull them out.
*
* See #MetaCullable and meta_cullable_cull_out() for more details.
*/
void
meta_cullable_cull_out_children (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
ClutterActor *actor = CLUTTER_ACTOR (cullable);
ClutterActor *child;
ClutterActorIter iter;
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
{
float x, y;
gboolean needs_culling;
if (!META_IS_CULLABLE (child))
continue;
needs_culling = (unobscured_region != NULL && clip_region != NULL);
if (needs_culling && !CLUTTER_ACTOR_IS_VISIBLE (child))
needs_culling = FALSE;
/* If an actor has effects applied, then that can change the area
* it paints and the opacity, so we no longer can figure out what
* portion of the actor is obscured and what portion of the screen
* it obscures, so we skip the actor.
*
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
* is applied to an actor, then our clipped redraws interfere with the
* caching of the FBO - even if we only need to draw a small portion
* of the window right now, ClutterOffscreenEffect may use other portions
* of the FBO later. So, skipping actors with effects applied also
* prevents these bugs.
*
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (needs_culling && clutter_actor_has_effects (child))
needs_culling = FALSE;
if (needs_culling && !meta_actor_is_untransformed (child, NULL, NULL))
needs_culling = FALSE;
if (needs_culling)
{
clutter_actor_get_position (child, &x, &y);
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (unobscured_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
cairo_region_translate (unobscured_region, x, y);
cairo_region_translate (clip_region, x, y);
}
else
{
meta_cullable_cull_out (META_CULLABLE (child), NULL, NULL);
}
}
}
/**
* meta_cullable_reset_culling_children:
* @cullable: The #MetaCullable
*
* This is a helper method for actors that want to recurse over their
* child actors, and cull them out.
*
* See #MetaCullable and meta_cullable_reset_culling() for more details.
*/
void
meta_cullable_reset_culling_children (MetaCullable *cullable)
{
ClutterActor *actor = CLUTTER_ACTOR (cullable);
ClutterActor *child;
ClutterActorIter iter;
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (!META_IS_CULLABLE (child))
continue;
meta_cullable_reset_culling (META_CULLABLE (child));
}
}
static void
meta_cullable_default_init (MetaCullableInterface *iface)
{
}
/**
* meta_cullable_cull_out:
* @cullable: The #MetaCullable
* @unobscured_region: The unobscured region, in @cullable's space.
* @clip_region: The clip region, in @cullable's space.
*
* When #MetaWindowGroup is painted, we walk over its direct cullable
* children from top to bottom and ask themselves to "cull out". Cullables
* can use @unobscured_region and @clip_region to clip their drawing. Actors
* interested in eliminating overdraw should copy the @clip_region and only
* paint those parts, as everything else has been obscured by actors above it.
*
* Actors that may have fully opaque parts should also subtract out a region
* that is fully opaque from @unobscured_region and @clip_region.
*
* @unobscured_region and @clip_region are extremely similar. The difference
* is that @clip_region starts off with the stage's clip, if Clutter detects
* that we're doing a clipped redraw. @unobscured_region, however, starts off
* with the full stage size, so actors that may want to record what parts of
* their window are unobscured for e.g. scheduling repaints can do so.
*
* Actors that have children can also use the meta_cullable_cull_out_children()
* helper method to do a simple cull across all their children.
*/
void
meta_cullable_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
META_CULLABLE_GET_IFACE (cullable)->cull_out (cullable, unobscured_region, clip_region);
}
/**
* meta_cullable_reset_culling:
* @cullable: The #MetaCullable
*
* Actors that copied data in their cull_out() implementation can now
* reset their data, as the paint is now over. Additional paints may be
* done by #ClutterClone or similar, and they should not be affected by
* the culling operation.
*/
void
meta_cullable_reset_culling (MetaCullable *cullable)
{
META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable);
}

View File

@ -0,0 +1,66 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 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, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Ray Strode <rstrode@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_CULLABLE_H__
#define __META_CULLABLE_H__
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define META_TYPE_CULLABLE (meta_cullable_get_type ())
#define META_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CULLABLE, MetaCullable))
#define META_IS_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CULLABLE))
#define META_CULLABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_CULLABLE, MetaCullableInterface))
typedef struct _MetaCullable MetaCullable;
typedef struct _MetaCullableInterface MetaCullableInterface;
struct _MetaCullableInterface
{
GTypeInterface g_iface;
void (* cull_out) (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void (* reset_culling) (MetaCullable *cullable);
};
GType meta_cullable_get_type (void);
void meta_cullable_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void meta_cullable_reset_culling (MetaCullable *cullable);
/* Utility methods for implementations */
void meta_cullable_cull_out_children (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void meta_cullable_reset_culling_children (MetaCullable *cullable);
G_END_DECLS
#endif /* __META_CULLABLE_H__ */

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <meta/meta-plugin.h>

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MODULE_H_

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
@ -326,3 +324,59 @@ meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
else
return meta_plugin_complete_display_change (plugin, TRUE);
}
gboolean
meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
if (klass->show_tile_preview)
{
klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number);
return TRUE;
}
return FALSE;
}
gboolean
meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
if (klass->hide_tile_preview)
{
klass->hide_tile_preview (plugin);
return TRUE;
}
return FALSE;
}
void
meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
MetaWindow *window)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return;
if (klass->show_window_menu)
klass->show_window_menu (plugin, window);
}

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_PLUGIN_MANAGER_H_
@ -77,4 +75,13 @@ gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin,
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number);
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
MetaWindow *window);
#endif

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -32,6 +30,7 @@
#include "meta-plugin-manager.h"
#include <meta/screen.h>
#include <meta/display.h>
#include <meta/util.h>
#include <string.h>
#include <X11/Xlib.h>

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__

View File

@ -13,9 +13,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**

View File

@ -28,17 +28,12 @@
#define __META_SHAPED_TEXTURE_PRIVATE_H__
#include <meta/meta-shaped-texture.h>
#include "meta-wayland-private.h"
ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
ClutterActor *meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface);
void meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface);
MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex);
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
Pixmap pixmap);
void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer);
ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture);
gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *stex,
cairo_rectangle_int_t *unobscured_bounds);
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
#endif

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -35,19 +33,16 @@
#include "meta-texture-tower.h"
#include "meta-shaped-texture-private.h"
#include "meta-wayland-private.h"
#include <cogl/cogl-wayland-server.h>
#include "meta-window-actor-private.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
#include "meta-cullable.h"
static void meta_shaped_texture_dispose (GObject *object);
static void meta_shaped_texture_paint (ClutterActor *actor);
static void meta_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color);
static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
gfloat for_height,
@ -61,15 +56,10 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
typedef enum _MetaShapedTextureType
{
META_SHAPED_TEXTURE_TYPE_X11_PIXMAP,
META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE,
} MetaShapedTextureType;
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_TYPE_ACTOR);
G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
@ -79,24 +69,16 @@ struct _MetaShapedTexturePrivate
{
MetaTextureTower *paint_tower;
MetaShapedTextureType type;
union {
struct {
Pixmap pixmap;
} x11;
struct {
MetaWaylandSurface *surface;
} wayland;
};
CoglTexture *texture;
CoglTexture *mask_texture;
cairo_region_t *clip_region;
cairo_region_t *input_shape_region;
/* The region containing only fully opaque pixels */
cairo_region_t *opaque_region;
/* MetaCullable regions, see that documentation for more details */
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
guint tex_width, tex_height;
guint create_mipmaps : 1;
@ -113,7 +95,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
actor_class->paint = meta_shaped_texture_paint;
actor_class->pick = meta_shaped_texture_pick;
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
@ -128,13 +109,37 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv->paint_tower = meta_texture_tower_new ();
priv->type = META_SHAPED_TEXTURE_TYPE_X11_PIXMAP;
priv->texture = NULL;
priv->mask_texture = NULL;
priv->create_mipmaps = TRUE;
}
static void
set_unobscured_region (MetaShapedTexture *self,
cairo_region_t *unobscured_region)
{
MetaShapedTexturePrivate *priv = self->priv;
g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
if (unobscured_region)
{
cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
priv->unobscured_region = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
}
}
static void
set_clip_region (MetaShapedTexture *self,
cairo_region_t *clip_region)
{
MetaShapedTexturePrivate *priv = self->priv;
g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
}
static void
meta_shaped_texture_dispose (GObject *object)
{
@ -149,7 +154,8 @@ meta_shaped_texture_dispose (GObject *object)
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
meta_shaped_texture_set_mask_texture (self, NULL);
meta_shaped_texture_set_clip_region (self, NULL);
set_unobscured_region (self, NULL);
set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
@ -220,10 +226,8 @@ paint_clipped_rectangle (CoglFramebuffer *fb,
cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
x1, y1, x2, y2,
&coords[0], 8);
}
static void
set_cogl_texture (MetaShapedTexture *stex,
CoglTexture *cogl_tex)
@ -238,10 +242,11 @@ set_cogl_texture (MetaShapedTexture *stex,
if (priv->texture)
cogl_object_unref (priv->texture);
priv->texture = cogl_object_ref (cogl_tex);
priv->texture = cogl_tex;
if (cogl_tex != NULL)
{
cogl_object_ref (cogl_tex);
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
@ -266,6 +271,9 @@ set_cogl_texture (MetaShapedTexture *stex,
* know how much of the buffer has changed with respect to the
* previous buffer. We only queue a redraw in response to surface
* damage. */
if (priv->create_mipmaps)
meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
}
static void
@ -324,15 +332,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
filter = COGL_PIPELINE_FILTER_LINEAR;
if (!clutter_actor_is_in_clone_paint (actor))
{
int x_origin, y_origin;
if (meta_actor_is_untransformed (actor,
&x_origin,
&y_origin))
filter = COGL_PIPELINE_FILTER_NEAREST;
}
if (!clutter_actor_is_in_clone_paint (actor) && meta_actor_is_untransformed (actor, NULL, NULL))
filter = COGL_PIPELINE_FILTER_NEAREST;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
@ -458,71 +459,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
cairo_region_destroy (blended_region);
}
static void
meta_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color)
{
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
if (!clutter_actor_should_pick_paint (actor) ||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
return;
/* If there is no region then use the regular pick */
if (priv->input_shape_region == NULL)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
else
{
int n_rects;
float *rectangles;
int i;
CoglPipeline *pipeline;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglColor cogl_color;
/* Note: We don't bother trying to intersect the pick and clip regions
* since needing to copy the region, do the intersection, and probably
* increase the number of rectangles seems more likely to have a negative
* effect.
*
* NB: Most of the time when just using rectangles for picking then
* picking shouldn't involve any rendering, and minimizing the number of
* rectangles has more benefit than reducing the area of the pick
* region.
*/
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
int pos = i * 4;
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
rectangles[pos] = rect.x;
rectangles[pos + 1] = rect.y;
rectangles[pos + 2] = rect.x + rect.width;
rectangles[pos + 3] = rect.y + rect.height;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color (pipeline, &cogl_color);
cogl_framebuffer_draw_rectangles (fb, pipeline,
rectangles, n_rects);
cogl_object_unref (pipeline);
}
}
static void
meta_shaped_texture_get_preferred_width (ClutterActor *self,
gfloat for_height,
@ -562,52 +498,37 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
}
static gboolean
meta_shaped_texture_get_paint_volume (ClutterActor *self,
meta_shaped_texture_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, self);
}
MetaShapedTexture *self = META_SHAPED_TEXTURE (actor);
cairo_rectangle_int_t unobscured_bounds;
ClutterActor *
meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface)
{
ClutterActor *actor = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (actor)->priv;
if (!clutter_paint_volume_set_from_allocation (volume, actor))
return FALSE;
/* XXX: it could probably be better to have a "type" construct-only
* property or create wayland/x11 subclasses */
priv->type = META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE;
if (meta_shaped_texture_get_unobscured_bounds (self, &unobscured_bounds))
{
ClutterVertex origin;
cairo_rectangle_int_t bounds;
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (actor),
surface);
/* I hate ClutterPaintVolume so much... */
clutter_paint_volume_get_origin (volume, &origin);
bounds.x = origin.x;
bounds.y = origin.y;
bounds.width = clutter_paint_volume_get_width (volume);
bounds.height = clutter_paint_volume_get_height (volume);
return actor;
}
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
void
meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface)
{
MetaShapedTexturePrivate *priv = stex->priv;
origin.x = bounds.x;
origin.y = bounds.y;
clutter_paint_volume_set_origin (volume, &origin);
clutter_paint_volume_set_width (volume, bounds.width);
clutter_paint_volume_set_height (volume, bounds.height);
}
priv->wayland.surface = surface;
if (surface && surface->buffer_ref.buffer)
meta_shaped_texture_attach_wayland_buffer (stex,
surface->buffer_ref.buffer);
}
MetaWaylandSurface *
meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
return priv->wayland.surface;
}
ClutterActor *
meta_shaped_texture_new_with_xwindow (Window xwindow)
{
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
return TRUE;
}
void
@ -652,110 +573,48 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
static void
wayland_surface_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
static cairo_region_t *
effective_unobscured_region (MetaShapedTexture *self)
{
MetaShapedTexturePrivate *priv;
MetaWaylandBuffer *buffer;
MetaShapedTexturePrivate *priv = self->priv;
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
priv = stex->priv;
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
return NULL;
g_return_if_fail (priv->type == META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE);
g_return_if_fail (priv->texture != NULL);
while (parent && !META_IS_WINDOW_ACTOR (parent))
parent = clutter_actor_get_parent (parent);
buffer = priv->wayland.surface->buffer_ref.buffer;
if (parent && clutter_actor_has_mapped_clones (parent))
return NULL;
if (buffer)
{
struct wl_resource *resource = buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglPixelFormat format;
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888;
break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888;
break;
#endif
default:
g_warn_if_reached ();
format = COGL_PIXEL_FORMAT_ARGB_8888;
}
cogl_texture_set_region (priv->texture,
x, y,
x, y,
width, height,
width, height,
format,
wl_shm_buffer_get_stride (shm_buffer),
wl_shm_buffer_get_data (shm_buffer));
}
}
return priv->unobscured_region;
}
static gboolean
get_clip (MetaShapedTexture *stex,
int x,
int y,
int width,
int height,
cairo_rectangle_int_t *clip)
gboolean
meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *self,
cairo_rectangle_int_t *unobscured_bounds)
{
ClutterActor *self = CLUTTER_ACTOR (stex);
MetaShapedTexturePrivate *priv;
ClutterActorBox allocation;
float scale_x;
float scale_y;
cairo_region_t *unobscured_region = effective_unobscured_region (self);
/* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's
* coordinate space so we need to convert from surface coordinates to
* actor coordinates...
*/
/* Calling clutter_actor_get_allocation_box() is enormously expensive
* if the actor has an out-of-date allocation, since it triggers
* a full redraw. clutter_actor_queue_redraw_with_clip() would redraw
* the whole stage anyways in that case, so just go ahead and do
* it here.
*/
if (!clutter_actor_has_allocation (self))
if (unobscured_region)
{
cairo_region_get_extents (unobscured_region, unobscured_bounds);
return TRUE;
}
else
return FALSE;
}
priv = stex->priv;
gboolean
meta_shaped_texture_is_obscured (MetaShapedTexture *self)
{
cairo_region_t *unobscured_region = effective_unobscured_region (self);
if (priv->tex_width == 0 || priv->tex_height == 0)
if (unobscured_region)
return cairo_region_is_empty (unobscured_region);
else
return FALSE;
clutter_actor_get_allocation_box (self, &allocation);
scale_x = (allocation.x2 - allocation.x1) / priv->tex_width;
scale_y = (allocation.y2 - allocation.y1) / priv->tex_height;
clip->x = x * scale_x;
clip->y = y * scale_y;
clip->width = width * scale_x;
clip->height = height * scale_y;
return TRUE;
}
/**
@ -765,14 +624,9 @@ get_clip (MetaShapedTexture *stex,
* @y: the y coordinate of the damaged area
* @width: the width of the damaged area
* @height: the height of the damaged area
* @unobscured_region: The unobscured region of the window or %NULL if
* there is no valid one (like when the actor is transformed or
* has a mapped clone)
*
* Repairs the damaged area indicated by @x, @y, @width and @height
* and queues a redraw for the intersection @visibible_region and
* the damage area. If @visibible_region is %NULL a redraw will always
* get queued.
* and potentially queues a redraw.
*
* Return value: Whether a redraw have been queued or not
*/
@ -781,33 +635,20 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height,
cairo_region_t *unobscured_region)
int height)
{
MetaShapedTexturePrivate *priv;
cairo_rectangle_int_t clip;
gboolean has_clip;
cairo_region_t *unobscured_region;
const cairo_rectangle_int_t clip = { x, y, width, height };
priv = stex->priv;
if (priv->texture == NULL)
return FALSE;
switch (priv->type)
{
case META_SHAPED_TEXTURE_TYPE_X11_PIXMAP:
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture),
x, y, width, height);
break;
case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE:
wayland_surface_update_area (stex, x, y, width, height);
break;
}
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
has_clip = get_clip (stex, x, y, width, height, &clip);
unobscured_region = effective_unobscured_region (stex);
if (unobscured_region)
{
cairo_region_t *intersection;
@ -816,8 +657,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
return FALSE;
intersection = cairo_region_copy (unobscured_region);
if (has_clip)
cairo_region_intersect_rectangle (intersection, &clip);
cairo_region_intersect_rectangle (intersection, &clip);
if (!cairo_region_is_empty (intersection))
{
@ -825,84 +665,31 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
cairo_region_get_extents (intersection, &damage_rect);
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
cairo_region_destroy (intersection);
return TRUE;
}
cairo_region_destroy (intersection);
return FALSE;
}
if (has_clip)
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
else
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
return TRUE;
{
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
return TRUE;
}
}
/**
* meta_shaped_texture_set_pixmap:
* meta_shaped_texture_set_texture:
* @stex: The #MetaShapedTexture
* @pixmap: The pixmap you want the stex to assume
* @pixmap: The #CoglTexture to display
*/
void
meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
Pixmap pixmap)
meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->x11.pixmap == pixmap)
return;
priv->x11.pixmap = pixmap;
if (pixmap != None)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglTexture *texture =
COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
set_cogl_texture (stex, texture);
}
else
set_cogl_texture (stex, NULL);
if (priv->create_mipmaps)
meta_texture_tower_set_base_texture (priv->paint_tower,
COGL_TEXTURE (priv->texture));
}
void
meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
/* TODO: we should change this api to be something like
* meta_shaped_texture_notify_buffer_attach() since we now maintain
* a reference to the MetaWaylandSurface where we can access the
* buffer without it being explicitly passed as an argument.
*/
g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer);
if (buffer)
set_cogl_texture (stex, buffer->texture);
else
set_cogl_texture (stex, NULL);
if (priv->create_mipmaps)
meta_texture_tower_set_base_texture (priv->paint_tower,
COGL_TEXTURE (priv->texture));
set_cogl_texture (stex, texture);
}
/**
@ -918,74 +705,6 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
return COGL_TEXTURE (stex->priv->texture);
}
/**
* meta_shaped_texture_set_input_shape_region:
* @stex: a #MetaShapedTexture
* @shape_region: the region of the texture that should respond to
* input.
*
* Determines what region of the texture should accept input. For
* X based windows this is defined by the ShapeInput region of the
* window.
*/
void
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
cairo_region_t *shape_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->input_shape_region != NULL)
{
cairo_region_destroy (priv->input_shape_region);
priv->input_shape_region = NULL;
}
if (shape_region != NULL)
{
cairo_region_reference (shape_region);
priv->input_shape_region = shape_region;
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* meta_shaped_texture_set_clip_region:
* @stex: a #MetaShapedTexture
* @clip_region: the region of the texture that is visible and
* should be painted.
*
* Provides a hint to the texture about what areas of the texture
* are not completely obscured and thus need to be painted. This
* is an optimization and is not supposed to have any effect on
* the output.
*
* Typically a parent container will set the clip region before
* painting its children, and then unset it afterwards.
*/
void
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->clip_region)
cairo_region_destroy (priv->clip_region);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
else
priv->clip_region = NULL;
}
/**
* meta_shaped_texture_set_opaque_region:
* @stex: a #MetaShapedTexture
@ -1113,3 +832,46 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
return surface;
}
static void
meta_shaped_texture_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable);
MetaShapedTexturePrivate *priv = self->priv;
set_unobscured_region (self, unobscured_region);
set_clip_region (self, clip_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff)
{
if (priv->opaque_region)
{
if (unobscured_region)
cairo_region_subtract (unobscured_region, priv->opaque_region);
if (clip_region)
cairo_region_subtract (clip_region, priv->opaque_region);
}
}
}
static void
meta_shaped_texture_reset_culling (MetaCullable *cullable)
{
MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable);
set_clip_region (self, NULL);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_shaped_texture_cull_out;
iface->reset_culling = meta_shaped_texture_reset_culling;
}
ClutterActor *
meta_shaped_texture_new (void)
{
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
}

View File

@ -0,0 +1,164 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 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.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-wayland.h"
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
#include "meta-wayland-private.h"
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
MetaWaylandBuffer *buffer;
};
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
static void
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
struct wl_resource *resource = priv->buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
}
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
{
/* XXX -- look at the SHM buffer format. */
return TRUE;
}
static gboolean
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
{
/* TODO: ensure that the buffer isn't NULL, implement
* wayland mapping semantics */
return TRUE;
}
static gboolean
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
{
return FALSE;
}
static void
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
/* Do nothing. In the future, we'll use KMS to set this
* up as a hardware overlay or something. */
}
static gboolean
meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
{
return FALSE;
}
static MetaWindow *
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
return priv->surface->window;
}
static void
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
{
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
}
static void
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
{
}
MetaSurfaceActor *
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
{
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
g_assert (meta_is_wayland_compositor ());
priv->surface = surface;
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
priv->buffer = buffer;
if (buffer)
meta_shaped_texture_set_texture (stex, buffer->texture);
else
meta_shaped_texture_set_texture (stex, NULL);
}
MetaWaylandSurface *
meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
return priv->surface;
}

View File

@ -0,0 +1,66 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 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.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
#define __META_SURFACE_ACTOR_WAYLAND_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include "meta-wayland.h"
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
struct _MetaSurfaceActorWayland
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorWaylandClass
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_wayland_get_type (void);
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */

View File

@ -0,0 +1,486 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 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.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-x11.h"
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <meta/errors.h>
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-cullable.h"
struct _MetaSurfaceActorX11Private
{
MetaWindow *window;
MetaDisplay *display;
CoglTexture *texture;
Pixmap pixmap;
Damage damage;
int last_width;
int last_height;
/* This is used to detect fullscreen windows that need to be unredirected */
guint full_damage_frames_count;
guint does_full_damage : 1;
/* Other state... */
guint argb32 : 1;
guint received_damage : 1;
guint size_changed : 1;
guint unredirected : 1;
};
typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR)
static void
free_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->damage == None)
return;
meta_error_trap_push (display);
XDamageDestroy (xdisplay, priv->damage);
priv->damage = None;
meta_error_trap_pop (display);
}
static void
detach_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
if (priv->pixmap == None)
return;
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
* you are supposed to be able to free a GLXPixmap after freeing the underlying
* pixmap, but it certainly doesn't work with current DRI/Mesa
*/
meta_shaped_texture_set_texture (stex, NULL);
cogl_flush ();
meta_error_trap_push (display);
XFreePixmap (xdisplay, priv->pixmap);
priv->pixmap = None;
meta_error_trap_pop (display);
cogl_object_unref (priv->texture);
priv->texture = NULL;
}
static void
set_pixmap (MetaSurfaceActorX11 *self,
Pixmap pixmap)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
CoglTexture *texture;
g_assert (priv->pixmap == None);
priv->pixmap = pixmap;
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n");
priv->texture = texture;
meta_shaped_texture_set_texture (stex, texture);
}
static void
update_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->size_changed)
{
detach_pixmap (self);
priv->size_changed = FALSE;
}
if (priv->pixmap == None)
{
Pixmap new_pixmap;
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
if (meta_error_trap_pop_with_return (display) != Success)
{
/* Probably a BadMatch if the window isn't viewable; we could
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
* to avoid this, but there's no reason to take two round trips
* when one will do. (We need that Sync if we want to handle failures
* for any reason other than !viewable. That's unlikely, but maybe
* we'll BadAlloc or something.)
*/
new_pixmap = None;
}
if (new_pixmap == None)
{
meta_verbose ("Unable to get named pixmap for %s\n",
meta_window_get_description (priv->window));
return;
}
set_pixmap (self, new_pixmap);
}
}
static gboolean
is_visible (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return (priv->pixmap != None) && !priv->unredirected;
}
static void
damage_area (MetaSurfaceActorX11 *self,
int x, int y, int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (!is_visible (self))
return;
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->received_damage = TRUE;
if (meta_window_is_fullscreen (priv->window) && !priv->unredirected && !priv->does_full_damage)
{
MetaRectangle window_rect;
meta_window_get_frame_rect (priv->window, &window_rect);
if (window_rect.x == x &&
window_rect.y == y &&
window_rect.width == width &&
window_rect.height == height)
priv->full_damage_frames_count++;
else
priv->full_damage_frames_count = 0;
if (priv->full_damage_frames_count >= 100)
priv->does_full_damage = TRUE;
}
/* Drop damage event for unredirected windows */
if (priv->unredirected)
return;
damage_area (self, x, y, width, height);
}
static void
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->received_damage)
{
meta_error_trap_push (display);
XDamageSubtract (xdisplay, priv->damage, None, None);
meta_error_trap_pop (display);
/* We need to make sure that any X drawing that happens before the
* XDamageSubtract() above is visible to subsequent GL rendering;
* the only standardized way to do this is EXT_x11_sync_object,
* which isn't yet widely available. For now, we count on details
* of Xorg and the open source drivers, and hope for the best
* otherwise.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use DamageReportBoundingBox
* there may be drawing between the last damage event and the
* XDamageSubtract() that needs to be flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any round trip
* request at this point is sufficient to flush the GLX buffers.
*/
XSync (xdisplay, False);
priv->received_damage = FALSE;
}
update_pixmap (self);
}
static void
update_is_argb32 (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
XRenderPictFormat *format;
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
}
static gboolean
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return priv->argb32;
}
static gboolean
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
return is_visible (self);
}
static gboolean
meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaWindow *window = priv->window;
if (meta_window_requested_dont_bypass_compositor (window))
return FALSE;
if (window->opacity != 0xFF)
return FALSE;
if (window->shape_region != NULL)
return FALSE;
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
return FALSE;
if (!meta_window_is_monitor_sized (window))
return FALSE;
if (meta_window_requested_bypass_compositor (window))
return TRUE;
if (meta_window_is_override_redirect (window))
return TRUE;
if (priv->does_full_damage)
return TRUE;
return FALSE;
}
static void
sync_unredirected (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
if (priv->unredirected)
{
detach_pixmap (self);
XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
}
else
{
XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
}
meta_error_trap_pop (display);
}
static void
meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->unredirected == unredirected)
return;
priv->unredirected = unredirected;
sync_unredirected (self);
}
static gboolean
meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return priv->unredirected;
}
static void
meta_surface_actor_x11_dispose (GObject *object)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
detach_pixmap (self);
free_damage (self);
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
}
static MetaWindow *
meta_surface_actor_x11_get_window (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor));
return priv->window;
}
static void
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
object_class->dispose = meta_surface_actor_x11_dispose;
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
surface_actor_class->get_window = meta_surface_actor_x11_get_window;
}
static void
meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->last_width = -1;
priv->last_height = -1;
}
static void
create_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
Display *xdisplay = meta_display_get_xdisplay (priv->display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
}
static void
window_decorated_notify (MetaWindow *window,
GParamSpec *pspec,
gpointer user_data)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
free_damage (self);
create_damage (self);
}
MetaSurfaceActor *
meta_surface_actor_x11_new (MetaWindow *window)
{
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = meta_window_get_display (window);
g_assert (!meta_is_wayland_compositor ());
priv->window = window;
priv->display = display;
create_damage (self);
g_signal_connect_object (priv->window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self, 0);
update_is_argb32 (self);
priv->unredirected = FALSE;
sync_unredirected (self);
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->last_width == width &&
priv->last_height == height)
return;
priv->size_changed = TRUE;
priv->last_width = width;
priv->last_height = height;
}

View File

@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 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.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_X11_H__
#define __META_SURFACE_ACTOR_X11_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include <X11/extensions/Xdamage.h>
#include <meta/display.h>
#include <meta/window.h>
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
struct _MetaSurfaceActorX11
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorX11Class
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_x11_get_type (void);
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_X11_H__ */

View File

@ -0,0 +1,319 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* SECTION:meta-surface-actor
* @title: MetaSurfaceActor
* @short_description: An actor representing a surface in the scene graph
*
* A surface can be either a shaped texture, or a group of shaped texture,
* used to draw the content of a window.
*/
#include <config.h>
#include "meta-surface-actor.h"
#include <clutter/clutter.h>
#include <meta/meta-shaped-texture.h>
#include "meta-cullable.h"
#include "meta-shaped-texture-private.h"
struct _MetaSurfaceActorPrivate
{
MetaShapedTexture *texture;
cairo_region_t *input_region;
/* Freeze/thaw accounting */
guint needs_damage_all : 1;
guint frozen : 1;
};
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
enum {
REPAINT_SCHEDULED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
gboolean
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
cairo_rectangle_int_t *unobscured_bounds)
{
MetaSurfaceActorPrivate *priv = self->priv;
return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
}
static void
meta_surface_actor_pick (ClutterActor *actor,
const ClutterColor *color)
{
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
MetaSurfaceActorPrivate *priv = self->priv;
if (!clutter_actor_should_pick_paint (actor))
return;
/* If there is no region then use the regular pick */
if (priv->input_region == NULL)
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color);
else
{
int n_rects;
float *rectangles;
int i;
CoglPipeline *pipeline;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglColor cogl_color;
n_rects = cairo_region_num_rectangles (priv->input_region);
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
int pos = i * 4;
cairo_region_get_rectangle (priv->input_region, i, &rect);
rectangles[pos + 0] = rect.x;
rectangles[pos + 1] = rect.y;
rectangles[pos + 2] = rect.x + rect.width;
rectangles[pos + 3] = rect.y + rect.height;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color (pipeline, &cogl_color);
cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
cogl_object_unref (pipeline);
}
}
static void
meta_surface_actor_dispose (GObject *object)
{
MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
MetaSurfaceActorPrivate *priv = self->priv;
g_clear_pointer (&priv->input_region, cairo_region_destroy);
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
}
static void
meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
object_class->dispose = meta_surface_actor_dispose;
actor_class->pick = meta_surface_actor_pick;
signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
}
static void
meta_surface_actor_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
static void
meta_surface_actor_reset_culling (MetaCullable *cullable)
{
meta_cullable_reset_culling_children (cullable);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_surface_actor_cull_out;
iface->reset_culling = meta_surface_actor_reset_culling;
}
static void
meta_surface_actor_init (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv;
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_SURFACE_ACTOR,
MetaSurfaceActorPrivate);
priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ());
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
}
cairo_surface_t *
meta_surface_actor_get_image (MetaSurfaceActor *self,
cairo_rectangle_int_t *clip)
{
return meta_shaped_texture_get_image (self->priv->texture, clip);
}
MetaShapedTexture *
meta_surface_actor_get_texture (MetaSurfaceActor *self)
{
return self->priv->texture;
}
void
meta_surface_actor_update_area (MetaSurfaceActor *self,
int x, int y, int width, int height)
{
MetaSurfaceActorPrivate *priv = self->priv;
if (meta_shaped_texture_update_area (priv->texture, x, y, width, height))
g_signal_emit (self, signals[REPAINT_SCHEDULED], 0);
}
gboolean
meta_surface_actor_is_obscured (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv = self->priv;
return meta_shaped_texture_is_obscured (priv->texture);
}
void
meta_surface_actor_set_input_region (MetaSurfaceActor *self,
cairo_region_t *region)
{
MetaSurfaceActorPrivate *priv = self->priv;
if (priv->input_region)
cairo_region_destroy (priv->input_region);
if (region)
priv->input_region = cairo_region_reference (region);
else
priv->input_region = NULL;
}
void
meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
cairo_region_t *region)
{
MetaSurfaceActorPrivate *priv = self->priv;
meta_shaped_texture_set_opaque_region (priv->texture, region);
}
static gboolean
is_frozen (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv = self->priv;
return priv->frozen;
}
void
meta_surface_actor_process_damage (MetaSurfaceActor *self,
int x, int y, int width, int height)
{
MetaSurfaceActorPrivate *priv = self->priv;
if (is_frozen (self))
{
/* The window is frozen due to an effect in progress: we ignore damage
* here on the off chance that this will stop the corresponding
* texture_from_pixmap from being update.
*
* needs_damage_all tracks that some unknown damage happened while the
* window was frozen so that when the window becomes unfrozen we can
* issue a full window update to cover any lost damage.
*
* It should be noted that this is an unreliable mechanism since it's
* quite likely that drivers will aim to provide a zero-copy
* implementation of the texture_from_pixmap extension and in those cases
* any drawing done to the window is always immediately reflected in the
* texture regardless of damage event handling.
*/
priv->needs_damage_all = TRUE;
return;
}
META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height);
}
void
meta_surface_actor_pre_paint (MetaSurfaceActor *self)
{
META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self);
}
gboolean
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
{
return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self);
}
gboolean
meta_surface_actor_is_visible (MetaSurfaceActor *self)
{
return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self);
}
void
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
gboolean frozen)
{
MetaSurfaceActorPrivate *priv = self->priv;
priv->frozen = frozen;
if (!frozen && priv->needs_damage_all)
{
/* Since we ignore damage events while a window is frozen for certain effects
* we may need to issue an update_area() covering the whole pixmap if we
* don't know what real damage has happened. */
meta_surface_actor_process_damage (self, 0, 0,
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
priv->needs_damage_all = FALSE;
}
}
gboolean
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
{
return META_SURFACE_ACTOR_GET_CLASS (self)->should_unredirect (self);
}
void
meta_surface_actor_set_unredirected (MetaSurfaceActor *self,
gboolean unredirected)
{
META_SURFACE_ACTOR_GET_CLASS (self)->set_unredirected (self, unredirected);
}
gboolean
meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
{
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
}
MetaWindow *
meta_surface_actor_get_window (MetaSurfaceActor *self)
{
return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self);
}

View File

@ -0,0 +1,86 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_SURFACE_ACTOR_PRIVATE_H
#define META_SURFACE_ACTOR_PRIVATE_H
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include <meta/window.h>
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR (meta_surface_actor_get_type())
#define META_SURFACE_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActor))
#define META_SURFACE_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass))
#define META_IS_SURFACE_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR))
#define META_IS_SURFACE_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR))
#define META_SURFACE_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass))
typedef struct _MetaSurfaceActor MetaSurfaceActor;
typedef struct _MetaSurfaceActorClass MetaSurfaceActorClass;
typedef struct _MetaSurfaceActorPrivate MetaSurfaceActorPrivate;
struct _MetaSurfaceActorClass
{
/*< private >*/
ClutterActorClass parent_class;
void (* process_damage) (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void (* pre_paint) (MetaSurfaceActor *actor);
gboolean (* is_argb32) (MetaSurfaceActor *actor);
gboolean (* is_visible) (MetaSurfaceActor *actor);
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
void (* set_unredirected) (MetaSurfaceActor *actor,
gboolean unredirected);
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
};
struct _MetaSurfaceActor
{
ClutterActor parent;
MetaSurfaceActorPrivate *priv;
};
GType meta_surface_actor_get_type (void);
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
cairo_rectangle_int_t *clip);
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
cairo_rectangle_int_t *unobscured_bounds);
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
cairo_region_t *region);
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
cairo_region_t *region);
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
gboolean frozen);
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected);
gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor);
G_END_DECLS
#endif /* META_SURFACE_ACTOR_PRIVATE_H */

View File

@ -18,9 +18,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -28,41 +26,6 @@
#include <clutter/clutter.h>
#include "meta-texture-rectangle.h"
CoglTexture *
meta_texture_rectangle_new (unsigned int width,
unsigned int height,
CoglPixelFormat format,
CoglPixelFormat internal_format,
unsigned int rowstride,
const guint8 *data,
GError **error)
{
ClutterBackend *backend =
clutter_get_default_backend ();
CoglContext *context =
clutter_backend_get_cogl_context (backend);
CoglTextureRectangle *tex_rect;
tex_rect = cogl_texture_rectangle_new_with_size (context,
width, height,
internal_format,
error);
if (tex_rect == NULL)
return NULL;
if (data)
cogl_texture_set_region (COGL_TEXTURE (tex_rect),
0, 0, /* src_x/y */
0, 0, /* dst_x/y */
width, height, /* dst_width/height */
width, height, /* width/height */
format,
rowstride,
data);
return COGL_TEXTURE (tex_rect);
}
static void
texture_rectangle_check_cb (CoglTexture *sub_texture,
const float *sub_texture_coords,

View File

@ -18,9 +18,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_TEXTURE_RECTANGLE_H__
@ -30,15 +28,6 @@
G_BEGIN_DECLS
CoglTexture *
meta_texture_rectangle_new (unsigned int width,
unsigned int height,
CoglPixelFormat format,
CoglPixelFormat internal_format,
unsigned int rowstride,
const guint8 *data,
GError **error);
gboolean
meta_texture_rectangle_check (CoglTexture *texture);

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
@ -357,18 +355,10 @@ texture_tower_create_texture (MetaTextureTower *tower,
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
meta_texture_rectangle_check (tower->textures[level - 1]))
{
tower->textures[level] =
meta_texture_rectangle_new (width, height,
/* data format */
TEXTURE_FORMAT,
/* internal cogl format */
TEXTURE_FORMAT,
/* rowstride */
width * 4,
/* data */
NULL,
/* error */
NULL);
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *context = clutter_backend_get_cogl_context (backend);
tower->textures[level] = cogl_texture_rectangle_new_with_size (context, width, height);
}
else
{

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_TEXTURE_TOWER_H__

View File

@ -5,11 +5,9 @@
#include <config.h>
#include <wayland-server.h>
#include <meta-wayland-private.h>
#include <X11/extensions/Xdamage.h>
#include <meta/compositor-mutter.h>
#include "meta-surface-actor.h"
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
@ -30,16 +28,6 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
int x,
int y,
int width,
int height);
void meta_window_actor_set_wayland_surface (MetaWindowActor *self,
MetaWaylandSurface *surface);
void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
MetaWaylandBuffer *buffer);
void meta_window_actor_pre_paint (MetaWindowActor *self);
void meta_window_actor_post_paint (MetaWindowActor *self);
void meta_window_actor_frame_complete (MetaWindowActor *self,
@ -48,13 +36,13 @@ void meta_window_actor_frame_complete (MetaWindowActor *self,
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
void meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state);
gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
void meta_window_actor_get_shape_bounds (MetaWindowActor *self,
cairo_rectangle_int_t *bounds);
gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
void meta_window_actor_set_unredirected (MetaWindowActor *self,
gboolean unredirected);
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
void meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
gboolean did_placement);
@ -68,18 +56,10 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
void meta_window_actor_set_clip_region (MetaWindowActor *self,
cairo_region_t *clip_region);
void meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region);
void meta_window_actor_reset_clip_regions (MetaWindowActor *self);
void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
cairo_region_t *unobscured_region);
void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
void meta_window_actor_update_surface (MetaWindowActor *self);
#endif /* META_WINDOW_ACTOR_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,8 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-background-actor-private.h"
#include "meta-background-group-private.h"
#include "window-private.h"
#include "meta-cullable.h"
struct _MetaWindowGroupClass
{
@ -27,7 +26,10 @@ struct _MetaWindowGroup
MetaScreen *screen;
};
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
/* Help macros to scale from OpenGL <-1,1> coordinates system to
* window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
@ -87,34 +89,40 @@ painting_untransformed (MetaWindowGroup *window_group,
return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin);
}
static void
meta_window_group_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
static void
meta_window_group_reset_culling (MetaCullable *cullable)
{
meta_cullable_reset_culling_children (cullable);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_window_group_cull_out;
iface->reset_culling = meta_window_group_reset_culling;
}
static void
meta_window_group_paint (ClutterActor *actor)
{
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
ClutterActorIter iter;
ClutterActor *child;
cairo_rectangle_int_t visible_rect, clip_rect;
int paint_x_offset, paint_y_offset;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int paint_x_offset, paint_y_offset;
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
ClutterActor *stage = clutter_actor_get_stage (actor);
/* Start off by treating all windows as completely unobscured, so damage anywhere
* in a window queues redraws, but confine it more below. */
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
meta_window_actor_set_unobscured_region (window_actor, NULL);
}
}
/* Normally we expect an actor to be drawn at it's position on the screen.
* However, if we're inside the paint of a ClutterClone, that won't be the
* case and we need to compensate. We look at the position of the window
@ -135,9 +143,6 @@ meta_window_group_paint (ClutterActor *actor)
return;
}
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
visible_rect.x = visible_rect.y = 0;
visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
@ -155,138 +160,44 @@ meta_window_group_paint (ClutterActor *actor)
clip_region = cairo_region_create_rectangle (&clip_rect);
if (!meta_is_wayland_compositor ())
{
info = meta_screen_get_compositor_data (window_group->screen);
if (info->unredirected_window != NULL)
{
cairo_rectangle_int_t unredirected_rect;
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
}
}
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
{
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
if (!meta_is_wayland_compositor () &&
info->unredirected_window != NULL &&
child == CLUTTER_ACTOR (info->unredirected_window))
continue;
/* If an actor has effects applied, then that can change the area
* it paints and the opacity, so we no longer can figure out what
* portion of the actor is obscured and what portion of the screen
* it obscures, so we skip the actor.
*
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
* is applied to an actor, then our clipped redraws interfere with the
* caching of the FBO - even if we only need to draw a small portion
* of the window right now, ClutterOffscreenEffect may use other portions
* of the FBO later. So, skipping actors with effects applied also
* prevents these bugs.
*
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (child))
continue;
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
continue;
x += paint_x_offset;
y += paint_y_offset;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (unobscured_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
meta_window_actor_set_unobscured_region (window_actor, unobscured_region);
meta_window_actor_set_clip_region (window_actor, clip_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
{
cairo_region_subtract (unobscured_region, obscured_region);
cairo_region_subtract (clip_region, obscured_region);
}
}
meta_window_actor_set_clip_region_beneath (window_actor, clip_region);
cairo_region_translate (unobscured_region, x, y);
cairo_region_translate (clip_region, x, y);
}
else if (META_IS_BACKGROUND_ACTOR (child) ||
META_IS_BACKGROUND_GROUP (child))
{
int x, y;
if (!meta_actor_is_untransformed (child, &x, &y))
continue;
x += paint_x_offset;
y += paint_y_offset;
cairo_region_translate (clip_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (child))
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region);
else
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region);
cairo_region_translate (clip_region, x, y);
}
}
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
cairo_region_destroy (unobscured_region);
cairo_region_destroy (clip_region);
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
/* Now that we are done painting, unset the visible regions (they will
* mess up painting clones of our actors)
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
meta_window_actor_reset_clip_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (child))
{
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
meta_background_actor_set_clip_region (background_actor, NULL);
}
}
meta_cullable_reset_culling (META_CULLABLE (window_group));
}
/* Adapted from clutter_actor_update_default_paint_volume() */
static gboolean
meta_window_group_get_paint_volume (ClutterActor *actor,
meta_window_group_get_paint_volume (ClutterActor *self,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
ClutterActorIter iter;
ClutterActor *child;
clutter_actor_iter_init (&iter, self);
while (clutter_actor_iter_next (&iter, &child))
{
const ClutterPaintVolume *child_volume;
if (!CLUTTER_ACTOR_IS_MAPPED (child))
continue;
child_volume = clutter_actor_get_transformed_paint_volume (child, self);
if (child_volume == NULL)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
return TRUE;
}
static void

View File

@ -11,29 +11,9 @@
* MetaWindowGroup:
*
* This class is a subclass of ClutterActor with special handling for
* MetaWindowActor/MetaBackgroundActor/MetaBackgroundGroup when painting
* children.
*
* When we are painting a stack of 5-10 maximized windows, the
* standard bottom-to-top method of drawing every actor results in a
* tremendous amount of overdraw and can easily max out the available
* memory bandwidth on a low-end graphics chipset. It's even worse if
* window textures are being accessed over the AGP bus.
*
* The basic technique applied here is to do a pre-pass before painting
* where we walk window from top to bottom and compute the visible area
* at each step by subtracting out the windows above it. The visible
* area is passed to MetaWindowActor which uses it to clip the portion of
* the window which drawn and avoid redrawing the shadow if it is completely
* obscured.
*
* A caveat is that this is ineffective if applications are using ARGB
* visuals, since we have no way of knowing whether a window obscures
* the windows behind it or not. Alternate approaches using the depth
* or stencil buffer rather than client side regions might be able to
* handle alpha windows, but the combination of glAlphaFunc and stenciling
* tends not to be efficient except on newer cards. (And on newer cards
* we have lots of memory and bandwidth.)
* #MetaCullable when painting children. It uses code similar to
* meta_cullable_cull_out_children(), but also has additional special
* cases for the undirected window, and similar.
*/
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_WINDOW_SHAPE_H__

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -34,13 +32,14 @@
#include <gmodule.h>
#include <string.h>
#define DESTROY_TIMEOUT 250
#define DESTROY_TIMEOUT 100
#define MINIMIZE_TIMEOUT 250
#define MAXIMIZE_TIMEOUT 250
#define MAP_TIMEOUT 250
#define SWITCH_TIMEOUT 500
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
#define SCREEN_TILE_PREVIEW_DATA_KEY "MCCP-Default-screen-tile-preview-data"
#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ())
#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
@ -69,6 +68,7 @@ struct _MetaDefaultPluginClass
};
static GQuark actor_data_quark = 0;
static GQuark screen_tile_preview_data_quark = 0;
static void start (MetaPlugin *plugin);
static void minimize (MetaPlugin *plugin,
@ -99,6 +99,12 @@ static void kill_window_effects (MetaPlugin *plugin,
MetaWindowActor *actor);
static void kill_switch_workspace (MetaPlugin *plugin);
static void show_tile_preview (MetaPlugin *plugin,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number);
static void hide_tile_preview (MetaPlugin *plugin);
static void confirm_display_change (MetaPlugin *plugin);
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
@ -145,6 +151,15 @@ typedef struct
} EffectCompleteData;
typedef struct _ScreenTilePreview
{
ClutterActor *actor;
GdkRGBA *preview_color;
MetaRectangle tile_rect;
} ScreenTilePreview;
static void
meta_default_plugin_dispose (GObject *object)
{
@ -205,6 +220,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
plugin_class->unmaximize = unmaximize;
plugin_class->destroy = destroy;
plugin_class->switch_workspace = switch_workspace;
plugin_class->show_tile_preview = show_tile_preview;
plugin_class->hide_tile_preview = hide_tile_preview;
plugin_class->plugin_info = plugin_info;
plugin_class->kill_window_effects = kill_window_effects;
plugin_class->kill_switch_workspace = kill_switch_workspace;
@ -291,26 +308,13 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
meta_plugin_switch_workspace_completed (plugin);
}
static gboolean
show_stage (MetaPlugin *plugin)
{
MetaScreen *screen;
ClutterActor *stage;
screen = meta_plugin_get_screen (plugin);
stage = meta_get_stage_for_screen (screen);
clutter_actor_show (stage);
return FALSE;
}
static void
on_monitors_changed (MetaScreen *screen,
MetaPlugin *plugin)
{
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
int i, n;
GRand *rand = g_rand_new_with_seed (12345);
clutter_actor_destroy_all_children (self->priv->background_group);
@ -333,14 +337,16 @@ on_monitors_changed (MetaScreen *screen,
reproducible.
*/
clutter_color_init (&color,
g_random_int () % 255,
g_random_int () % 255,
g_random_int () % 255,
g_rand_int_range (rand, 0, 255),
g_rand_int_range (rand, 0, 255),
g_rand_int_range (rand, 0, 255),
255);
clutter_actor_set_background_color (background, &color);
clutter_actor_add_child (self->priv->background_group, background);
}
g_rand_free (rand);
}
static void
@ -357,10 +363,7 @@ start (MetaPlugin *plugin)
G_CALLBACK (on_monitors_changed), plugin);
on_monitors_changed (screen, plugin);
meta_later_add (META_LATER_BEFORE_REDRAW,
(GSourceFunc) show_stage,
plugin,
NULL);
clutter_actor_show (meta_get_stage_for_screen (screen));
}
static void
@ -409,9 +412,11 @@ switch_workspace (MetaPlugin *plugin,
MetaWindowActor *window_actor = l->data;
ActorPrivate *apriv = get_actor_private (window_actor);
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWorkspace *workspace;
gint win_workspace;
win_workspace = meta_window_actor_get_workspace (window_actor);
workspace = meta_window_get_workspace (meta_window_actor_get_meta_window (window_actor));
win_workspace = meta_workspace_index (workspace);
if (win_workspace == to || win_workspace == from)
{
@ -483,8 +488,6 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
/* FIXME - we shouldn't assume the original scale, it should be saved
* at the start of the effect */
clutter_actor_set_scale (data->actor, 1.0, 1.0);
clutter_actor_move_anchor_point_from_gravity (data->actor,
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
meta_plugin_minimize_completed (plugin, window_actor);
@ -521,9 +524,6 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
apriv->is_minimized = TRUE;
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MINIMIZE_TIMEOUT,
@ -562,8 +562,6 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
/* FIXME - don't assume the original scale was 1.0 */
clutter_actor_set_scale (data->actor, 1.0, 1.0);
clutter_actor_move_anchor_point_from_gravity (data->actor,
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
meta_plugin_maximize_completed (plugin, window_actor);
@ -588,10 +586,8 @@ maximize (MetaPlugin *plugin,
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
gdouble scale_x = 1.0;
gdouble scale_y = 1.0;
gfloat anchor_x = 0;
gfloat anchor_y = 0;
gdouble scale_x = 1.0;
gdouble scale_y = 1.0;
type = meta_window_get_window_type (meta_window);
@ -615,13 +611,6 @@ maximize (MetaPlugin *plugin,
scale_x = (gdouble)end_width / (gdouble) width;
scale_y = (gdouble)end_height / (gdouble) height;
anchor_x = (gdouble)(x - end_x)*(gdouble)width /
((gdouble)(end_width - width));
anchor_y = (gdouble)(y - end_y)*(gdouble)height /
((gdouble)(end_height - height));
clutter_actor_move_anchor_point (actor, anchor_x, anchor_y);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MAXIMIZE_TIMEOUT,
@ -676,9 +665,6 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
apriv->tml_map = NULL;
clutter_actor_move_anchor_point_from_gravity (data->actor,
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
meta_plugin_map_completed (plugin, window_actor);
@ -704,15 +690,15 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
clutter_actor_set_scale (actor, 0.0, 0.0);
clutter_actor_set_pivot_point (actor, 0.5, 0.5);
clutter_actor_set_opacity (actor, 0);
clutter_actor_set_scale (actor, 0.5, 0.5);
clutter_actor_show (actor);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE,
CLUTTER_EASE_OUT_QUAD,
MAP_TIMEOUT,
"opacity", 255,
"scale-x", 1.0,
"scale-y", 1.0,
NULL);
@ -764,14 +750,12 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE,
CLUTTER_EASE_OUT_QUAD,
DESTROY_TIMEOUT,
"scale-x", 0.0,
"scale-y", 1.0,
"opacity", 0,
"scale-x", 0.8,
"scale-y", 0.8,
NULL);
apriv->tml_destroy = clutter_animation_get_timeline (animation);
data->plugin = plugin;
@ -784,6 +768,82 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
meta_plugin_destroy_completed (plugin, window_actor);
}
/*
* Tile preview private data accessor
*/
static void
free_screen_tile_preview (gpointer data)
{
ScreenTilePreview *preview = data;
if (G_LIKELY (preview != NULL)) {
clutter_actor_destroy (preview->actor);
g_slice_free (ScreenTilePreview, preview);
}
}
static ScreenTilePreview *
get_screen_tile_preview (MetaScreen *screen)
{
ScreenTilePreview *preview = g_object_get_qdata (G_OBJECT (screen), screen_tile_preview_data_quark);
if (G_UNLIKELY (screen_tile_preview_data_quark == 0))
screen_tile_preview_data_quark = g_quark_from_static_string (SCREEN_TILE_PREVIEW_DATA_KEY);
if (G_UNLIKELY (!preview))
{
preview = g_slice_new0 (ScreenTilePreview);
preview->actor = clutter_actor_new ();
clutter_actor_set_background_color (preview->actor, CLUTTER_COLOR_Blue);
clutter_actor_set_opacity (preview->actor, 100);
clutter_actor_add_child (meta_get_window_group_for_screen (screen), preview->actor);
g_object_set_qdata_full (G_OBJECT (screen),
screen_tile_preview_data_quark, preview,
free_screen_tile_preview);
}
return preview;
}
static void
show_tile_preview (MetaPlugin *plugin,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number)
{
MetaScreen *screen = meta_plugin_get_screen (plugin);
ScreenTilePreview *preview = get_screen_tile_preview (screen);
ClutterActor *window_actor;
if (CLUTTER_ACTOR_IS_VISIBLE (preview->actor)
&& preview->tile_rect.x == tile_rect->x
&& preview->tile_rect.y == tile_rect->y
&& preview->tile_rect.width == tile_rect->width
&& preview->tile_rect.height == tile_rect->height)
return; /* nothing to do */
clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y);
clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height);
clutter_actor_show (preview->actor);
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
clutter_actor_lower (preview->actor, window_actor);
preview->tile_rect = *tile_rect;
}
static void
hide_tile_preview (MetaPlugin *plugin)
{
MetaScreen *screen = meta_plugin_get_screen (plugin);
ScreenTilePreview *preview = get_screen_tile_preview (screen);
clutter_actor_hide (preview->actor);
}
static void
kill_switch_workspace (MetaPlugin *plugin)
{

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "region-utils.h"

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __META_REGION_UTILS_H__

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* The standard cycle-windows keybinding should be the key above the

View File

@ -366,11 +366,25 @@ meta_barrier_fire_event (MetaBarrier *barrier,
}
gboolean
meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *xev)
meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event)
{
MetaBarrier *barrier;
XIBarrierEvent *xev;
if (event == NULL)
return FALSE;
switch (event->evtype)
{
case XI_BarrierHit:
case XI_BarrierLeave:
break;
default:
return FALSE;
}
xev = (XIBarrierEvent *) event;
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
if (barrier != NULL)
{

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <X11/Xlib.h>

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_BOXES_PRIVATE_H

View File

@ -25,9 +25,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "boxes-private.h"

View File

@ -18,9 +18,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -118,8 +116,6 @@ typedef struct
{
MetaRectangle orig;
MetaRectangle current;
MetaFrameBorders *borders;
gboolean must_free_borders;
ActionType action_type;
gboolean is_user_action;
@ -195,7 +191,6 @@ static gboolean constrain_partially_onscreen (MetaWindow *window,
static void setup_constraint_info (ConstraintInfo *info,
MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
@ -204,13 +199,12 @@ static void place_window_if_needed (MetaWindow *window,
ConstraintInfo *info);
static void update_onscreen_requirements (MetaWindow *window,
ConstraintInfo *info);
static void extend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders);
static void unextend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders);
static inline void get_size_limits (const MetaWindow *window,
const MetaFrameBorders *borders,
gboolean include_frame,
static void extend_by_frame (MetaWindow *window,
MetaRectangle *rect);
static void unextend_by_frame (MetaWindow *window,
MetaRectangle *rect);
static inline void get_size_limits (MetaWindow *window,
gboolean include_frame,
MetaRectangle *min_size,
MetaRectangle *max_size);
@ -280,7 +274,6 @@ do_all_constraints (MetaWindow *window,
void
meta_window_constrain (MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
@ -303,7 +296,6 @@ meta_window_constrain (MetaWindow *window,
setup_constraint_info (&info,
window,
orig_borders,
flags,
resize_gravity,
orig,
@ -333,19 +325,11 @@ meta_window_constrain (MetaWindow *window,
* if this was a user move or user move-and-resize operation.
*/
update_onscreen_requirements (window, &info);
/* Ew, what an ugly way to do things. Destructors (in a real OOP language,
* not gobject-style--gobject would be more pain than it's worth) or
* smart pointers would be so much nicer here. *shrug*
*/
if (info.must_free_borders)
g_free (info.borders);
}
static void
setup_constraint_info (ConstraintInfo *info,
MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
@ -357,18 +341,6 @@ setup_constraint_info (ConstraintInfo *info,
info->orig = *orig;
info->current = *new;
/* Create a fake frame geometry if none really exists */
if (orig_borders && !window->fullscreen)
{
info->borders = orig_borders;
info->must_free_borders = FALSE;
}
else
{
info->borders = g_new0 (MetaFrameBorders, 1);
info->must_free_borders = TRUE;
}
if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION)
info->action_type = ACTION_MOVE_AND_RESIZE;
else if (flags & META_IS_RESIZE_ACTION)
@ -453,8 +425,9 @@ setup_constraint_info (ConstraintInfo *info,
* the monitor.
*/
if (meta_prefs_get_force_fullscreen() &&
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
!window->hide_titlebar_when_maximized &&
window->decorated &&
(window->decorated || !meta_window_is_client_decorated (window)) &&
meta_rectangle_equal (new, &monitor_info->rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
@ -519,11 +492,17 @@ place_window_if_needed(MetaWindow *window,
!window->minimized &&
!window->fullscreen)
{
MetaRectangle placed_rect = info->orig;
MetaRectangle orig_rect;
MetaRectangle placed_rect;
MetaWorkspace *cur_workspace;
const MetaMonitorInfo *monitor_info;
meta_window_place (window, info->borders, info->orig.x, info->orig.y,
meta_window_get_frame_rect (window, &placed_rect);
orig_rect = info->orig;
extend_by_frame (window, &orig_rect);
meta_window_place (window, orig_rect.x, orig_rect.y,
&placed_rect.x, &placed_rect.y);
did_placement = TRUE;
@ -541,6 +520,7 @@ place_window_if_needed(MetaWindow *window,
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
info->current.x = placed_rect.x;
info->current.y = placed_rect.y;
@ -586,10 +566,6 @@ place_window_if_needed(MetaWindow *window,
(window->maximize_vertically_after_placement ?
META_MAXIMIZE_VERTICAL : 0), &info->current);
/* maximization may have changed frame geometry */
if (!window->fullscreen)
meta_frame_calc_borders (window->frame, info->borders);
if (window->fullscreen_after_placement)
{
window->saved_rect = info->current;
@ -649,7 +625,7 @@ update_onscreen_requirements (MetaWindow *window,
/* The require onscreen/on-single-monitor and titlebar_visible
* stuff is relative to the outer window, not the inner
*/
extend_by_frame (&info->current, info->borders);
extend_by_frame (window, &info->current);
/* Update whether we want future constraint runs to require the
* window to be on fully onscreen.
@ -682,10 +658,13 @@ update_onscreen_requirements (MetaWindow *window,
*/
if (window->frame && window->decorated)
{
MetaFrameBorders borders;
MetaRectangle titlebar_rect;
meta_frame_calc_borders (window->frame, &borders);
titlebar_rect = info->current;
titlebar_rect.height = info->borders->visible.top;
titlebar_rect.height = borders.visible.top;
old = window->require_titlebar_visible;
window->require_titlebar_visible =
meta_rectangle_overlaps_with_region (info->usable_screen_region,
@ -698,39 +677,33 @@ update_onscreen_requirements (MetaWindow *window,
}
/* Don't forget to restore the position of the window */
unextend_by_frame (&info->current, info->borders);
unextend_by_frame (window, &info->current);
}
static void
extend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders)
extend_by_frame (MetaWindow *window,
MetaRectangle *rect)
{
rect->x -= borders->visible.left;
rect->y -= borders->visible.top;
rect->width += borders->visible.left + borders->visible.right;
rect->height += borders->visible.top + borders->visible.bottom;
meta_window_client_rect_to_frame_rect (window, rect, rect);
}
static void
unextend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders)
unextend_by_frame (MetaWindow *window,
MetaRectangle *rect)
{
rect->x += borders->visible.left;
rect->y += borders->visible.top;
rect->width -= borders->visible.left + borders->visible.right;
rect->height -= borders->visible.top + borders->visible.bottom;
meta_window_frame_rect_to_client_rect (window, rect, rect);
}
static inline void
get_size_limits (const MetaWindow *window,
const MetaFrameBorders *borders,
gboolean include_frame,
get_size_limits (MetaWindow *window,
gboolean include_frame,
MetaRectangle *min_size,
MetaRectangle *max_size)
{
/* We pack the results into MetaRectangle structs just for convienience; we
* don't actually use the position of those rects.
*/
min_size->x = min_size->y = max_size->x = max_size->y = 0;
min_size->width = window->size_hints.min_width;
min_size->height = window->size_hints.min_height;
max_size->width = window->size_hints.max_width;
@ -738,22 +711,8 @@ get_size_limits (const MetaWindow *window,
if (include_frame)
{
int fw = borders->visible.left + borders->visible.right;
int fh = borders->visible.top + borders->visible.bottom;
min_size->width += fw;
min_size->height += fh;
/* Do check to avoid overflow (e.g. max_size->width & max_size->height
* may be set to G_MAXINT by meta_set_normal_hints()).
*/
if (max_size->width < (G_MAXINT - fw))
max_size->width += fw;
else
max_size->width = G_MAXINT;
if (max_size->height < (G_MAXINT - fh))
max_size->height += fh;
else
max_size->height = G_MAXINT;
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
}
}
@ -765,18 +724,28 @@ constrain_modal_dialog (MetaWindow *window,
{
int x, y;
MetaWindow *parent = meta_window_get_transient_for (window);
MetaRectangle child_rect, parent_rect;
gboolean constraint_already_satisfied;
if (!meta_window_is_attached_dialog (window))
return TRUE;
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
y = parent->rect.y + (parent->rect.height / 2 - info->current.height / 2);
if (parent->frame)
{
x += parent->frame->rect.x;
y += parent->frame->rect.y;
}
/* We want to center the dialog on the parent, including the decorations
for both of them. info->current is in client X window coordinates, so we need
to convert them to frame coordinates, apply the centering and then
convert back to client.
*/
child_rect = info->current;
extend_by_frame (window, &child_rect);
meta_window_get_frame_rect (parent, &parent_rect);
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
unextend_by_frame (window, &child_rect);
x = child_rect.x;
y = child_rect.y;
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
@ -841,19 +810,19 @@ constrain_maximization (MetaWindow *window,
active_workspace_struts = window->screen->active_workspace->all_struts;
target_size = info->current;
extend_by_frame (&target_size, info->borders);
extend_by_frame (window, &target_size);
meta_rectangle_expand_to_avoiding_struts (&target_size,
&info->entire_monitor,
direction,
active_workspace_struts);
}
/* Now make target_size = maximized size of client window */
unextend_by_frame (&target_size, info->borders);
/* unextend_by_frame (window, &target_size); */
/* Check min size constraints; max size constraints are ignored for maximized
* windows, as per bug 327543.
*/
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width && window->maximized_horizontally;
vminbad = target_size.height < min_size.height && window->maximized_vertically;
if (hminbad || vminbad)
@ -907,12 +876,12 @@ constrain_tiling (MetaWindow *window,
* use an external function for the actual calculation
*/
meta_window_get_current_tile_area (window, &target_size);
unextend_by_frame (&target_size, info->borders);
unextend_by_frame (window, &target_size);
/* Check min size constraints; max size constraints are ignored as for
* maximized windows.
*/
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width;
vminbad = target_size.height < min_size.height;
if (hminbad || vminbad)
@ -955,7 +924,7 @@ constrain_fullscreen (MetaWindow *window,
monitor = info->entire_monitor;
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
if (too_big || too_small)
@ -1064,7 +1033,7 @@ constrain_size_limits (MetaWindow *window,
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
/* We ignore max-size limits for maximized windows; see #327543 */
if (window->maximized_horizontally)
max_size.width = MAX (max_size.width, info->current.width);
@ -1256,8 +1225,8 @@ do_screen_and_monitor_relative_constraints (
/* Determine whether constraint applies; exit if it doesn't */
how_far_it_can_be_smushed = info->current;
get_size_limits (window, info->borders, TRUE, &min_size, &max_size);
extend_by_frame (&info->current, info->borders);
get_size_limits (window, TRUE, &min_size, &max_size);
extend_by_frame (window, &info->current);
if (info->action_type != ACTION_MOVE)
{
@ -1277,7 +1246,7 @@ do_screen_and_monitor_relative_constraints (
&info->current);
if (exit_early || constraint_satisfied || check_only)
{
unextend_by_frame (&info->current, info->borders);
unextend_by_frame (window, &info->current);
return constraint_satisfied;
}
@ -1301,7 +1270,7 @@ do_screen_and_monitor_relative_constraints (
info->fixed_directions,
&info->current);
unextend_by_frame (&info->current, info->borders);
unextend_by_frame (window, &info->current);
return TRUE;
}
@ -1390,7 +1359,6 @@ constrain_titlebar_visible (MetaWindow *window,
window->type == META_WINDOW_DOCK ||
window->fullscreen ||
!window->require_titlebar_visible ||
!window->decorated ||
unconstrained_user_action)
return TRUE;
@ -1414,8 +1382,11 @@ constrain_titlebar_visible (MetaWindow *window,
*/
if (window->frame)
{
bottom_amount = info->current.height + info->borders->visible.bottom;
vert_amount_onscreen = info->borders->visible.top;
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
bottom_amount = info->current.height + borders.visible.bottom;
vert_amount_onscreen = borders.visible.top;
}
else
bottom_amount = vert_amount_offscreen;
@ -1489,8 +1460,11 @@ constrain_partially_onscreen (MetaWindow *window,
*/
if (window->frame)
{
bottom_amount = info->current.height + info->borders->visible.bottom;
vert_amount_onscreen = info->borders->visible.top;
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
bottom_amount = info->current.height + borders.visible.bottom;
vert_amount_onscreen = borders.visible.top;
}
else
bottom_amount = vert_amount_offscreen;

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_CONSTRAINTS_H
@ -40,7 +38,6 @@ typedef enum
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,

View File

@ -18,9 +18,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -172,6 +170,7 @@ meta_core_queue_frame_resize (Display *xdisplay,
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_frame_size_changed (window);
}
void
@ -282,8 +281,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
return;
changes.stack_mode = Below;
changes.sibling = grab_window->frame ? grab_window->frame->xwindow
: grab_window->xwindow;
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
@ -330,8 +328,7 @@ meta_core_maximize (Display *xdisplay,
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
meta_window_maximize (window, META_MAXIMIZE_BOTH);
}
void
@ -344,11 +341,9 @@ meta_core_toggle_maximize_vertically (Display *xdisplay,
meta_window_raise (window);
if (META_WINDOW_MAXIMIZED_VERTICALLY (window))
meta_window_unmaximize (window,
META_MAXIMIZE_VERTICAL);
meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
else
meta_window_maximize (window,
META_MAXIMIZE_VERTICAL);
meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
}
void
@ -361,11 +356,9 @@ meta_core_toggle_maximize_horizontally (Display *xdisplay,
meta_window_raise (window);
if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window))
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL);
meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
else
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL);
meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
}
void
@ -378,11 +371,9 @@ meta_core_toggle_maximize (Display *xdisplay,
meta_window_raise (window);
if (META_WINDOW_MAXIMIZED (window))
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
else
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
meta_window_maximize (window, META_MAXIMIZE_BOTH);
}
void
@ -394,8 +385,7 @@ meta_core_unmaximize (Display *xdisplay,
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
}
void
@ -479,9 +469,6 @@ meta_core_change_workspace (Display *xdisplay,
void
meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,
int root_x,
int root_y,
int button,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
@ -490,121 +477,7 @@ meta_core_show_window_menu (Display *xdisplay,
meta_window_raise (window);
meta_window_focus (window, timestamp);
meta_window_show_menu (window, root_x, root_y, button, timestamp);
}
void
meta_core_get_menu_accelerator (MetaMenuOp menu_op,
int workspace,
unsigned int *keysym,
MetaVirtualModifier *modifiers)
{
const char *name;
name = NULL;
switch (menu_op)
{
case META_MENU_OP_NONE:
/* No keybinding for this one */
break;
case META_MENU_OP_DELETE:
name = "close";
break;
case META_MENU_OP_MINIMIZE:
name = "minimize";
break;
case META_MENU_OP_UNMAXIMIZE:
name = "unmaximize";
break;
case META_MENU_OP_MAXIMIZE:
name = "maximize";
break;
case META_MENU_OP_UNSHADE:
case META_MENU_OP_SHADE:
name = "toggle_shaded";
break;
case META_MENU_OP_UNSTICK:
case META_MENU_OP_STICK:
name = "toggle-on-all-workspaces";
break;
case META_MENU_OP_ABOVE:
case META_MENU_OP_UNABOVE:
name = "toggle-above";
break;
case META_MENU_OP_WORKSPACES:
switch (workspace)
{
case 1:
name = "move-to-workspace-1";
break;
case 2:
name = "move-to-workspace-2";
break;
case 3:
name = "move-to-workspace-3";
break;
case 4:
name = "move-to-workspace-4";
break;
case 5:
name = "move-to-workspace-5";
break;
case 6:
name = "move-to-workspace-6";
break;
case 7:
name = "move-to-workspace-7";
break;
case 8:
name = "move-to-workspace-8";
break;
case 9:
name = "move-to-workspace-9";
break;
case 10:
name = "move-to-workspace-10";
break;
case 11:
name = "move-to-workspace-11";
break;
case 12:
name = "move-to-workspace-12";
break;
}
break;
case META_MENU_OP_MOVE:
name = "begin-move";
break;
case META_MENU_OP_RESIZE:
name = "begin-resize";
break;
case META_MENU_OP_MOVE_LEFT:
name = "move-to-workspace-left";
break;
case META_MENU_OP_MOVE_RIGHT:
name = "move-to-workspace-right";
break;
case META_MENU_OP_MOVE_UP:
name = "move-to-workspace-up";
break;
case META_MENU_OP_MOVE_DOWN:
name = "move-to-workspace-down";
break;
case META_MENU_OP_RECOVER:
/* No keybinding for this one */
break;
}
if (name)
{
meta_prefs_get_window_binding (name, keysym, modifiers);
}
else
{
*keysym = 0;
*modifiers = 0;
}
meta_window_show_menu (window);
}
const char*

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_CORE_H
@ -161,15 +159,8 @@ const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
void meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,
int root_x,
int root_y,
int button,
guint32 timestamp);
void meta_core_get_menu_accelerator (MetaMenuOp menu_op,
int workspace,
unsigned int *keysym,
MetaVirtualModifier *modifiers);
gboolean meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#define _XOPEN_SOURCE /* for kill() */
@ -39,18 +37,17 @@
#include <stdlib.h>
#include <stdio.h>
#include "meta-wayland-surface.h"
static void meta_window_present_delete_dialog (MetaWindow *window,
guint32 timestamp);
static void
delete_ping_reply_func (MetaDisplay *display,
Window xwindow,
delete_ping_reply_func (MetaWindow *window,
guint32 timestamp,
void *user_data)
{
meta_topic (META_DEBUG_PING,
"Got reply to delete ping for %s\n",
((MetaWindow*)user_data)->desc);
meta_topic (META_DEBUG_PING, "Got reply to delete ping for %s\n", window->desc);
/* we do nothing */
}
@ -68,12 +65,10 @@ dialog_exited (GPid pid, int status, gpointer user_data)
}
static void
delete_ping_timeout_func (MetaDisplay *display,
Window xwindow,
delete_ping_timeout_func (MetaWindow *window,
guint32 timestamp,
void *user_data)
{
MetaWindow *window = user_data;
char *window_title;
gchar *window_content, *tmp;
GPid dialog_pid;
@ -137,36 +132,42 @@ void
meta_window_check_alive (MetaWindow *window,
guint32 timestamp)
{
meta_display_ping_window (window->display,
window,
meta_display_ping_window (window,
timestamp,
delete_ping_reply_func,
delete_ping_timeout_func,
window);
NULL);
}
void
meta_window_delete (MetaWindow *window,
guint32 timestamp)
{
meta_error_trap_push (window->display);
if (window->delete_window)
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Deleting %s with delete_window request\n",
window->desc);
meta_window_send_icccm_message (window,
window->display->atom_WM_DELETE_WINDOW,
timestamp);
meta_error_trap_push (window->display);
if (window->delete_window)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Deleting %s with delete_window request\n",
window->desc);
meta_window_send_icccm_message (window,
window->display->atom_WM_DELETE_WINDOW,
timestamp);
}
else
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Deleting %s with explicit kill\n",
window->desc);
XKillClient (window->display->xdisplay, window->xwindow);
}
meta_error_trap_pop (window->display);
}
else
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Deleting %s with explicit kill\n",
window->desc);
XKillClient (window->display->xdisplay, window->xwindow);
meta_wayland_surface_delete (window->surface);
}
meta_error_trap_pop (window->display);
meta_window_check_alive (window, timestamp);

View File

@ -19,9 +19,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_DISPLAY_PRIVATE_H
@ -39,6 +37,7 @@
#include "keybindings-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
#ifdef HAVE_STARTUP_NOTIFICATION
#include <libsn/sn.h>
@ -56,10 +55,9 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
guint32 timestamp,
gpointer user_data);
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
guint32 timestamp,
gpointer user_data);
typedef enum {
META_LIST_DEFAULT = 0, /* normal windows */
@ -86,14 +84,6 @@ typedef enum {
META_TILE_MAXIMIZED
} MetaTileMode;
typedef enum {
META_FOCUS_NONE = 0,
META_FOCUS_X_CLIENT = 1,
META_FOCUS_WAYLAND_CLIENT = 2,
META_FOCUS_NO_FOCUS_WINDOW = 3,
META_FOCUS_STAGE = 4
} MetaFocusType;
struct _MetaDisplay
{
GObject parent_instance;
@ -101,6 +91,8 @@ struct _MetaDisplay
char *name;
Display *xdisplay;
int clutter_event_filter;
Window leader_window;
Window timestamp_pinging_window;
@ -125,7 +117,6 @@ struct _MetaDisplay
* like the no_focus_window or the stage X window. */
Window focus_xwindow;
gulong focus_serial;
MetaFocusType focus_type;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
@ -147,6 +138,14 @@ struct _MetaDisplay
*/
guint allow_terminal_deactivation : 1;
/* If true, server->focus_serial refers to us changing the focus; in
* this case, we can ignore focus events that have exactly focus_serial,
* since we take care to make another request immediately afterwards.
* But if focus is being changed by another client, we have to accept
* multiple events with the same serial.
*/
guint focused_by_us : 1;
guint static_gravity_works : 1;
/*< private-ish >*/
@ -189,7 +188,7 @@ struct _MetaDisplay
MetaWindow* autoraise_window;
/* Alt+click button grabs */
unsigned int window_grab_modifiers;
ClutterModifierType window_grab_modifiers;
/* current window operation */
MetaGrabOp grab_op;
@ -216,7 +215,6 @@ struct _MetaDisplay
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time;
guint32 grab_motion_notify_time;
GList* grab_old_window_stacking;
MetaEdgeResistanceData *grab_edge_resistance_data;
unsigned int grab_last_user_action_was_snap;
@ -234,8 +232,8 @@ struct _MetaDisplay
int grab_resize_timeout_id;
/* Keybindings stuff */
MetaKeyBinding *key_bindings;
int n_key_bindings;
GHashTable *key_bindings;
GHashTable *key_bindings_index;
int min_keycode;
int max_keycode;
KeySym *keymap;
@ -265,10 +263,6 @@ struct _MetaDisplay
/* Managed by group.c */
GHashTable *groups_by_leader;
/* currently-active window menu if any */
MetaWindowMenu *window_menu;
MetaWindow *window_with_menu;
/* Managed by window-props.c */
MetaWindowPropHooks *prop_hooks_table;
GHashTable *prop_hooks;
@ -445,14 +439,13 @@ void meta_display_retheme_all (void);
void meta_display_set_cursor_theme (const char *theme,
int size);
void meta_display_ping_window (MetaDisplay *display,
MetaWindow *window,
void meta_display_ping_window (MetaWindow *window,
guint32 timestamp,
MetaWindowPingFunc ping_reply_func,
MetaWindowPingFunc ping_timeout_func,
void *user_data);
gboolean meta_display_window_has_pending_pings (MetaDisplay *display,
MetaWindow *window);
void meta_display_pong_for_serial (MetaDisplay *display,
guint32 serial);
int meta_resize_gravity_from_grab_op (MetaGrabOp op);
@ -473,27 +466,22 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
ClutterKeyEvent *event);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
gboolean meta_display_handle_event (MetaDisplay *display,
XEvent *event);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *event);
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event);
#endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp);
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
Window window,
guint32 timestamp);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -985,7 +983,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
{
MetaRectangle *new_rect;
new_rect = g_new (MetaRectangle, 1);
meta_window_get_outer_rect (cur_window, new_rect);
meta_window_get_frame_rect (cur_window, new_rect);
obscuring_windows = g_slist_prepend (obscuring_windows, new_rect);
window_stacking =
g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position));
@ -1010,7 +1008,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
{
MetaRectangle cur_rect;
MetaWindow *cur_window = cur_window_iter->data;
meta_window_get_outer_rect (cur_window, &cur_rect);
meta_window_get_frame_rect (cur_window, &cur_rect);
/* Check if we want to use this window's edges for edge
* resistance (note that dock edges are considered screen edges
@ -1151,7 +1149,7 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
MetaRectangle old_outer, proposed_outer, new_outer;
gboolean is_resize;
meta_window_get_outer_rect (window, &old_outer);
meta_window_get_frame_rect (window, &old_outer);
proposed_outer = old_outer;
proposed_outer.x += (*new_x - old_x);
@ -1237,7 +1235,7 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
int proposed_outer_width, proposed_outer_height;
gboolean is_resize;
meta_window_get_outer_rect (window, &old_outer);
meta_window_get_frame_rect (window, &old_outer);
proposed_outer_width = old_outer.width + (*new_width - old_width);
proposed_outer_height = old_outer.height + (*new_height - old_height);
meta_rectangle_resize_with_gravity (&old_outer,

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_EDGE_RESISTANCE_H

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**

View File

@ -18,9 +18,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -52,9 +50,6 @@ meta_window_ensure_frame (MetaWindow *window)
if (window->frame)
return;
/* See comment below for why this is required. */
meta_display_grab (window->display);
frame = g_new (MetaFrame, 1);
frame->window = window;
@ -67,8 +62,8 @@ meta_window_ensure_frame (MetaWindow *window)
frame->right_width = 0;
frame->current_cursor = 0;
frame->mapped = FALSE;
frame->is_flashing = FALSE;
frame->borders_cached = FALSE;
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
window->desc,
@ -119,14 +114,6 @@ meta_window_ensure_frame (MetaWindow *window)
meta_display_register_x_window (window->display, &frame->xwindow, window);
/* Reparent the client window; it may be destroyed,
* thus the error trap. We'll get a destroy notify later
* and free everything. Comment in FVWM source code says
* we need a server grab or the child can get its MapNotify
* before we've finished reparenting and getting the decoration
* window onscreen, so ensure_frame must be called with
* a grab.
*/
meta_error_trap_push (window->display);
if (window->mapped)
{
@ -170,7 +157,7 @@ meta_window_ensure_frame (MetaWindow *window)
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);
meta_display_ungrab (window->display);
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
}
void
@ -334,9 +321,23 @@ meta_frame_calc_borders (MetaFrame *frame,
if (frame == NULL)
meta_frame_borders_clear (borders);
else
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
borders);
{
if (!frame->borders_cached)
{
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
&frame->cached_borders);
frame->borders_cached = TRUE;
}
*borders = frame->cached_borders;
}
}
void
meta_frame_clear_cached_borders (MetaFrame *frame)
{
frame->borders_cached = FALSE;
}
gboolean

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_FRAME_PRIVATE_H
@ -41,15 +39,17 @@ struct _MetaFrame
*/
MetaRectangle rect;
MetaFrameBorders cached_borders; /* valid if borders_cached is set */
/* position of client, size of frame */
int child_x;
int child_y;
int right_width;
int bottom_height;
guint mapped : 1;
guint need_reapply_frame_shape : 1;
guint is_flashing : 1; /* used by the visual bell flash */
guint borders_cached : 1;
};
void meta_window_ensure_frame (MetaWindow *window);
@ -68,6 +68,8 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
gboolean need_move,
gboolean need_resize);
void meta_frame_clear_cached_borders (MetaFrame *frame);
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
void meta_frame_get_mask (MetaFrame *frame,

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_GROUP_PRIVATE_H

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_GROUP_PROPS_H

View File

@ -15,9 +15,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_ICON_CACHE_H

View File

@ -21,9 +21,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_KEYBINDINGS_PRIVATE_H
@ -32,6 +30,7 @@
#include <gio/gio.h>
#include <meta/keybindings.h>
typedef struct _MetaKeyHandler MetaKeyHandler;
struct _MetaKeyHandler
{
char *name;
@ -49,9 +48,48 @@ struct _MetaKeyBinding
KeyCode keycode;
unsigned int mask;
MetaVirtualModifier modifiers;
gint flags;
MetaKeyHandler *handler;
};
/**
* MetaKeyCombo:
* @keysym: keysym
* @keycode: keycode
* @modifiers: modifiers
*/
typedef struct _MetaKeyCombo MetaKeyCombo;
struct _MetaKeyCombo
{
unsigned int keysym;
unsigned int keycode;
MetaVirtualModifier modifiers;
};
typedef struct
{
char *name;
GSettings *settings;
MetaKeyBindingAction action;
/*
* A list of MetaKeyCombos. Each of them is bound to
* this keypref. If one has keysym==modifiers==0, it is
* ignored.
*/
GSList *combos;
/* for keybindings that can have shift or not like Alt+Tab */
gboolean add_shift:1;
/* for keybindings that apply only to a window */
gboolean per_window:1;
/* for keybindings not added with meta_display_add_keybinding() */
gboolean builtin:1;
} MetaKeyPref;
void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
@ -66,9 +104,9 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
guint32 timestamp);
void meta_window_ungrab_all_keys (MetaWindow *window,
guint32 timestamp);
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XIDeviceEvent *event);
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
ClutterKeyEvent *event);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);
@ -79,9 +117,8 @@ gboolean meta_prefs_add_keybinding (const char *name,
gboolean meta_prefs_remove_keybinding (const char *name);
GList *meta_prefs_get_keybindings (void);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -44,7 +42,7 @@
*/
#define _GNU_SOURCE
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
#include <config.h>
#include <meta/main.h>
@ -55,7 +53,7 @@
#include "session.h"
#include <meta/prefs.h>
#include <meta/compositor.h>
#include "meta-wayland-private.h"
#include "meta-wayland.h"
#include <glib-object.h>
#include <glib-unix.h>
@ -192,6 +190,7 @@ static gboolean opt_replace_wm;
static gboolean opt_disable_sm;
static gboolean opt_sync;
static gboolean opt_wayland;
static gboolean opt_display_server;
static GOptionEntry meta_options[] = {
{
@ -235,6 +234,11 @@ static GOptionEntry meta_options[] = {
N_("Run as a wayland compositor"),
NULL
},
{
"display-server", 0, 0, G_OPTION_ARG_NONE,
&opt_display_server,
N_("Run as a full display server, rather than nested")
},
{NULL}
};
@ -256,19 +260,8 @@ meta_get_option_context (void)
bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
/* We must set the windowing backend here, because Clutter creates the backend
object when the first call is made.
We consider running from mutter-launch equivalent to running from bare metal.
*/
if (getenv ("WESTON_LAUNCHER_SOCK"))
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
ctx = g_option_context_new (NULL);
g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE);
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
g_option_context_add_group (ctx, cogl_get_option_group ());
return ctx;
}
@ -304,8 +297,12 @@ event_dispatch (GSource *source,
gpointer user_data)
{
ClutterEvent *event = clutter_event_get ();
if (event)
clutter_do_event (event);
{
clutter_do_event (event);
clutter_event_free (event);
}
return TRUE;
}
@ -343,16 +340,17 @@ meta_clutter_init (void)
* also is %NULL, use the default - :0.0
*/
static void
meta_select_display (gchar *display_name)
meta_select_display (char *display_arg)
{
gchar *envVar = "";
const char *display_name;
if (display_arg)
display_name = (const char *) display_arg;
else
display_name = g_getenv ("MUTTER_DISPLAY");
if (display_name)
envVar = g_strconcat ("DISPLAY=", display_name, NULL);
else if (g_getenv ("MUTTER_DISPLAY"))
envVar = g_strconcat ("DISPLAY=",
g_getenv ("MUTTER_DISPLAY"), NULL);
/* DO NOT FREE envVar, putenv() sucks */
putenv (envVar);
g_setenv ("DISPLAY", display_name, TRUE);
}
static void
@ -387,7 +385,8 @@ meta_init (void)
{
struct sigaction act;
sigset_t empty_mask;
ClutterSettings *clutter_settings;
sigemptyset (&empty_mask);
act.sa_handler = SIG_IGN;
act.sa_mask = empty_mask;
@ -408,6 +407,9 @@ meta_init (void)
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
if (opt_display_server)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
meta_set_is_wayland_compositor (opt_wayland);
if (g_get_home_dir ())
@ -439,7 +441,7 @@ meta_init (void)
meta_fatal ("Can't specify both SM save file and SM client id\n");
meta_main_loop = g_main_loop_new (NULL, FALSE);
meta_ui_init ();
/* If we are running with wayland then we don't wait until we have
@ -453,6 +455,13 @@ meta_init (void)
*/
meta_clutter_init ();
}
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
* for now.
*/
clutter_settings = clutter_settings_get_default ();
g_object_set (clutter_settings, "window-scaling-factor", 1, NULL);
}
/**
@ -493,6 +502,32 @@ meta_register_with_session (void)
g_free (opt_client_id);
}
/**
* meta_activate_session:
*
* Tells mutter to activate the session. When mutter is a
* Wayland compositor, this tells logind to switch over to
* the new session.
*/
gboolean
meta_activate_session (void)
{
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
GError *error = NULL;
if (!meta_wayland_compositor_activate_session (compositor, &error))
{
g_warning ("Could not activate session: %s\n", error->message);
g_error_free (error);
return FALSE;
}
}
return TRUE;
}
/**
* meta_run: (skip)
*

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
@ -31,18 +29,21 @@
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_revert_root (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
void meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage);
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
#endif

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
@ -41,6 +39,7 @@
#include <gbm.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
@ -68,11 +67,34 @@ struct _MetaCursorTracker {
MetaScreen *screen;
gboolean is_showing;
gboolean has_cursor;
gboolean has_hw_cursor;
MetaCursorReference *sprite;
/* The cursor tracker stores the cursor for the current grab
* operation, the cursor for the window with pointer focus, and
* the cursor for the root window, which contains either the
* default arrow cursor or the 'busy' hourglass if we're launching
* an app.
*
* We choose the first one available -- if there's a grab cursor,
* we choose that cursor, if there's window cursor, we choose that,
* otherwise we choose the root cursor.
*
* The displayed_cursor contains the chosen cursor.
*/
MetaCursorReference *displayed_cursor;
MetaCursorReference *grab_cursor;
/* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything.
* So, we can't simply store a NULL in window_cursor to
* determine an unset window cursor; we need an extra boolean.
*/
gboolean has_window_cursor;
MetaCursorReference *window_cursor;
MetaCursorReference *root_cursor;
MetaCursorReference *default_cursors[META_CURSOR_LAST];
int current_x, current_y;
@ -98,12 +120,10 @@ enum {
static guint signals[LAST_SIGNAL];
static void meta_cursor_tracker_set_sprite (MetaCursorTracker *tracker,
MetaCursorReference *sprite);
static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has_hw_cursor);
static void sync_cursor (MetaCursorTracker *tracker);
static MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
@ -286,7 +306,6 @@ meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
self->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
COGL_PIXEL_FORMAT_ANY,
rowstride,
(uint8_t*)image->pixels,
NULL);
@ -346,7 +365,7 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
ClutterBackend *backend;
CoglContext *cogl_context;
MetaCursorReference *self;
CoglPixelFormat cogl_format, cogl_internal_format;
CoglPixelFormat cogl_format;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
@ -354,7 +373,7 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
self->ref_count = 1;
self->hot_x = hot_x;
self->hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
@ -370,37 +389,31 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
cogl_internal_format = COGL_PIXEL_FORMAT_ANY;
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
cogl_internal_format = COGL_PIXEL_FORMAT_RGB_888;
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
cogl_internal_format = COGL_PIXEL_FORMAT_ANY;
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
cogl_internal_format = COGL_PIXEL_FORMAT_BGR_888;
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
cogl_internal_format = COGL_PIXEL_FORMAT_ANY;
gbm_format = GBM_FORMAT_ARGB8888;
}
self->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
cogl_internal_format,
rowstride,
wl_shm_buffer_get_data (shm_buffer),
NULL);
@ -456,47 +469,10 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
if (tracker->gbm)
{
cogl_format = cogl_texture_get_format (COGL_TEXTURE (self->texture));
switch (cogl_format)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
case COGL_PIXEL_FORMAT_ARGB_8888_PRE:
case COGL_PIXEL_FORMAT_ARGB_8888:
gbm_format = GBM_FORMAT_BGRA8888;
break;
case COGL_PIXEL_FORMAT_BGRA_8888_PRE:
case COGL_PIXEL_FORMAT_BGRA_8888:
break;
case COGL_PIXEL_FORMAT_RGB_888:
break;
#else
case COGL_PIXEL_FORMAT_ARGB_8888_PRE:
case COGL_PIXEL_FORMAT_ARGB_8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case COGL_PIXEL_FORMAT_BGRA_8888_PRE:
case COGL_PIXEL_FORMAT_BGRA_8888:
gbm_format = GBM_FORMAT_BGRA8888;
break;
case COGL_PIXEL_FORMAT_RGB_888:
gbm_format = GBM_FORMAT_RGB888;
break;
#endif
default:
meta_warning ("Unknown cogl format %d\n", cogl_format);
return self;
}
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
GBM_BO_USE_CURSOR_64X64))
{
self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!self->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!self->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
}
@ -520,8 +496,8 @@ meta_cursor_tracker_finalize (GObject *object)
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
int i;
if (self->sprite)
meta_cursor_reference_unref (self->sprite);
if (self->displayed_cursor)
meta_cursor_reference_unref (self->displayed_cursor);
if (self->root_cursor)
meta_cursor_reference_unref (self->root_cursor);
@ -594,10 +570,18 @@ make_wayland_cursor_tracker (MetaScreen *screen)
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = self;
meta_cursor_tracker_update_position (self,
wl_fixed_to_int (compositor->seat->pointer.x),
wl_fixed_to_int (compositor->seat->pointer.y));
self->drm_fd = compositor->drm_fd;
if (self->drm_fd >= 0)
self->gbm = gbm_create_device (compositor->drm_fd);
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
self->gbm = gbm_create_device (self->drm_fd);
}
#endif
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
@ -635,17 +619,27 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
if (screen->cursor_tracker)
return screen->cursor_tracker;
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
self = make_wayland_cursor_tracker (screen);
else
#endif
self = make_x11_cursor_tracker (screen);
screen->cursor_tracker = self;
return self;
}
static void
set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->window_cursor = meta_cursor_reference_ref (cursor);
tracker->has_window_cursor = has_cursor;
sync_cursor (tracker);
}
gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
@ -662,8 +656,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
set_window_cursor (tracker, FALSE, NULL);
return TRUE;
}
@ -677,7 +670,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
gboolean free_cursor_data;
CoglContext *ctx;
if (tracker->sprite)
if (tracker->has_window_cursor)
return;
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
@ -715,7 +708,6 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
cursor_image->width,
cursor_image->height,
CLUTTER_CAIRO_FORMAT_ARGB32,
COGL_PIXEL_FORMAT_ANY,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
@ -725,9 +717,11 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (sprite != NULL)
{
tracker->sprite = meta_cursor_reference_take_texture (sprite);
tracker->sprite->hot_x = cursor_image->xhot;
tracker->sprite->hot_y = cursor_image->yhot;
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite);
cursor->hot_x = cursor_image->xhot;
cursor->hot_y = cursor_image->yhot;
set_window_cursor (tracker, TRUE, cursor);
}
XFree (cursor_image);
}
@ -745,8 +739,8 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (tracker->sprite)
return COGL_TEXTURE (tracker->sprite->texture);
if (tracker->displayed_cursor)
return COGL_TEXTURE (tracker->displayed_cursor->texture);
else
return NULL;
}
@ -768,12 +762,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (tracker->sprite)
if (tracker->displayed_cursor)
{
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
if (x)
*x = tracker->sprite->hot_x;
*x = displayed_cursor->hot_x;
if (y)
*y = tracker->sprite->hot_y;
*y = displayed_cursor->hot_y;
}
else
{
@ -788,14 +783,46 @@ static MetaCursorReference *
ensure_wayland_cursor (MetaCursorTracker *tracker,
MetaCursor cursor)
{
if (tracker->default_cursors[cursor])
return tracker->default_cursors[cursor];
tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor);
if (!tracker->default_cursors[cursor])
meta_warning ("Failed to load cursor from theme\n");
{
tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor);
if (!tracker->default_cursors[cursor])
meta_warning ("Failed to load cursor from theme\n");
}
return tracker->default_cursors[cursor];
return meta_cursor_reference_ref (tracker->default_cursors[cursor]);
}
void
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursor cursor)
{
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
if (cursor != META_CURSOR_DEFAULT)
tracker->grab_cursor = ensure_wayland_cursor (tracker, cursor);
sync_cursor (tracker);
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *cursor;
if (buffer)
cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
else
cursor = NULL;
set_window_cursor (tracker, TRUE, cursor);
}
void
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
{
set_window_cursor (tracker, FALSE, NULL);
}
void
@ -815,21 +842,12 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
/* Now update the real root cursor */
if (meta_is_wayland_compositor ())
{
MetaCursorReference *ref;
ref = ensure_wayland_cursor (tracker, cursor);
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
tracker->root_cursor = meta_cursor_reference_ref (ref);
tracker->root_cursor = ensure_wayland_cursor (tracker, cursor);
sync_cursor (tracker);
}
}
void
meta_cursor_tracker_revert_root (MetaCursorTracker *tracker)
{
meta_cursor_tracker_set_sprite (tracker, tracker->root_cursor);
}
static void
update_hw_cursor (MetaCursorTracker *tracker)
{
@ -838,7 +856,7 @@ update_hw_cursor (MetaCursorTracker *tracker)
unsigned int i, n_crtcs;
gboolean enabled;
enabled = tracker->has_cursor && tracker->sprite->bo != NULL;
enabled = tracker->displayed_cursor && tracker->displayed_cursor->bo != NULL;
tracker->has_hw_cursor = enabled;
monitors = meta_monitor_manager_get ();
@ -884,105 +902,51 @@ move_hw_cursor (MetaCursorTracker *tracker)
}
}
void
meta_cursor_tracker_set_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *new_cursor;
if (!tracker->is_showing)
return NULL;
if (buffer)
{
new_cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
meta_cursor_tracker_set_sprite (tracker, new_cursor);
meta_cursor_reference_unref (new_cursor);
}
else
meta_cursor_tracker_set_sprite (tracker, NULL);
if (tracker->grab_cursor)
return tracker->grab_cursor;
if (tracker->has_window_cursor)
return tracker->window_cursor;
return tracker->root_cursor;
}
static void
meta_cursor_tracker_set_sprite (MetaCursorTracker *tracker,
MetaCursorReference *sprite)
sync_displayed_cursor (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (sprite == tracker->sprite)
if (tracker->displayed_cursor == displayed_cursor)
return;
g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref);
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
if (sprite)
if (meta_is_wayland_compositor ())
{
tracker->sprite = meta_cursor_reference_ref (sprite);
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (tracker->sprite->texture));
}
else
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
if (displayed_cursor)
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (displayed_cursor->texture));
else
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
tracker->has_cursor = tracker->sprite != NULL && tracker->is_showing;
update_hw_cursor (tracker);
update_hw_cursor (tracker);
}
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
meta_cursor_tracker_update_position (tracker, tracker->current_x, tracker->current_y);
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
tracker->current_x = new_x;
tracker->current_y = new_y;
if (tracker->sprite)
{
tracker->current_rect.x = tracker->current_x - tracker->sprite->hot_x;
tracker->current_rect.y = tracker->current_y - tracker->sprite->hot_y;
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (tracker->sprite->texture));
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (tracker->sprite->texture));
}
else
{
tracker->current_rect.x = 0;
tracker->current_rect.y = 0;
tracker->current_rect.width = 0;
tracker->current_rect.height = 0;
}
if (tracker->has_hw_cursor)
move_hw_cursor (tracker);
}
void
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->has_hw_cursor || !tracker->has_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
tracker->pipeline,
tracker->current_rect.x,
tracker->current_rect.y,
tracker->current_rect.x +
tracker->current_rect.width,
tracker->current_rect.y +
tracker->current_rect.height);
tracker->previous_rect = tracker->current_rect;
tracker->previous_is_valid = TRUE;
}
void
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage)
static void
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
cairo_rectangle_int_t clip;
g_assert (meta_is_wayland_compositor ());
@ -999,7 +963,7 @@ meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
tracker->previous_is_valid = FALSE;
}
if (tracker->has_hw_cursor || !tracker->has_cursor)
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
return;
clip.x = tracker->current_rect.x;
@ -1009,6 +973,72 @@ meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
clutter_actor_queue_redraw_with_clip (stage, &clip);
}
static void
sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor;
sync_displayed_cursor (tracker);
displayed_cursor = tracker->displayed_cursor;
if (displayed_cursor)
{
tracker->current_rect.x = tracker->current_x - displayed_cursor->hot_x;
tracker->current_rect.y = tracker->current_y - displayed_cursor->hot_y;
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (displayed_cursor->texture));
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (displayed_cursor->texture));
}
else
{
tracker->current_rect.x = 0;
tracker->current_rect.y = 0;
tracker->current_rect.width = 0;
tracker->current_rect.height = 0;
}
if (meta_is_wayland_compositor ())
{
if (tracker->has_hw_cursor)
move_hw_cursor (tracker);
else
meta_cursor_tracker_queue_redraw (tracker);
}
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
tracker->current_x = new_x;
tracker->current_y = new_y;
sync_cursor (tracker);
}
void
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
tracker->pipeline,
tracker->current_rect.x,
tracker->current_rect.y,
tracker->current_rect.x +
tracker->current_rect.width,
tracker->current_rect.y +
tracker->current_rect.height);
tracker->previous_rect = tracker->current_rect;
tracker->previous_is_valid = TRUE;
}
static void
meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
@ -1016,15 +1046,16 @@ meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
{
if (has)
{
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
handle = gbm_bo_get_handle (tracker->sprite->bo);
width = gbm_bo_get_width (tracker->sprite->bo);
height = gbm_bo_get_height (tracker->sprite->bo);
hot_x = tracker->sprite->hot_x;
hot_y = tracker->sprite->hot_y;
handle = gbm_bo_get_handle (displayed_cursor->bo);
width = gbm_bo_get_width (displayed_cursor->bo);
height = gbm_bo_get_height (displayed_cursor->bo);
hot_x = displayed_cursor->hot_x;
hot_y = displayed_cursor->hot_y;
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
@ -1047,12 +1078,13 @@ get_pointer_position_gdk (int *x,
GdkScreen *gscreen;
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
gdevice = gdk_device_manager_get_client_pointer (gmanager);
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
gdk_device_get_position (gdevice, &gscreen, x, y);
gdk_device_get_state (gdevice,
gdk_screen_get_root_window (gscreen),
NULL, (GdkModifierType*)mods);
if (mods)
gdk_device_get_state (gdevice,
gdk_screen_get_root_window (gscreen),
NULL, (GdkModifierType*)mods);
}
static void
@ -1068,9 +1100,12 @@ get_pointer_position_clutter (int *x,
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
clutter_input_device_get_coords (cdevice, NULL, &point);
*x = point.x;
*y = point.y;
*mods = clutter_input_device_get_modifier_state (cdevice);
if (x)
*x = point.x;
if (y)
*y = point.y;
if (mods)
*mods = clutter_input_device_get_modifier_state (cdevice);
}
void
@ -1100,13 +1135,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
tracker->has_cursor = tracker->sprite != NULL && visible;
update_hw_cursor (tracker);
meta_cursor_tracker_queue_redraw (tracker, compositor->stage);
sync_cursor (tracker);
}
else
{
@ -1118,3 +1147,12 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
tracker->screen->xroot);
}
}
void
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
update_hw_cursor (tracker);
sync_cursor (tracker);
}

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
@ -537,7 +535,7 @@ make_watch (MetaIdleMonitor *monitor,
watch->timeout_source = source;
}
}
else
else if (monitor->user_active_alarm != None)
{
if (timeout_msec != 0)
{
@ -655,8 +653,10 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
{
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
g_object_ref (monitor);
g_hash_table_remove (monitor->watches,
GUINT_TO_POINTER (id));
g_object_unref (monitor);
}
/**
@ -949,6 +949,8 @@ on_bus_acquired (GDBusConnection *connection,
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_slist_free (devices);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",

View File

@ -13,9 +13,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)

View File

@ -20,9 +20,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
@ -817,6 +815,22 @@ meta_monitor_config_match_current (MetaMonitorConfig *self,
return ok;
}
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
unsigned int i;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
if (outputs[i].hotplug_mode_update)
return TRUE;
return FALSE;
}
static MetaConfiguration *
meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaOutput *outputs,

View File

@ -111,8 +111,7 @@ make_output_name (drmModeConnector *connector)
};
const char *connector_type_name;
if (connector->connector_type >= 0 &&
connector->connector_type < G_N_ELEMENTS (connector_type_names))
if (connector->connector_type < G_N_ELEMENTS (connector_type_names))
connector_type_name = connector_type_names[connector->connector_type];
else
connector_type_name = "unknown";
@ -651,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
state = DRM_MODE_DPMS_SUSPEND;
break;
case META_POWER_SAVE_OFF:
state = DRM_MODE_DPMS_SUSPEND;
state = DRM_MODE_DPMS_OFF;
break;
default:
return;

View File

@ -29,9 +29,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_PRIVATE_H
@ -44,9 +42,7 @@
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
#endif
#include "meta-xrandr-shared.h"
#include "meta-dbus-xrandr.h"
@ -56,19 +52,6 @@ typedef struct _MetaMonitorManager MetaMonitorManager;
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
typedef struct _MetaMonitorConfig MetaMonitorConfig;
#ifndef HAVE_WAYLAND
enum wl_output_transform {
WL_OUTPUT_TRANSFORM_NORMAL,
WL_OUTPUT_TRANSFORM_90,
WL_OUTPUT_TRANSFORM_180,
WL_OUTPUT_TRANSFORM_270,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
#endif
typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCRTC MetaCRTC;
typedef struct _MetaMonitorMode MetaMonitorMode;
@ -119,6 +102,9 @@ struct _MetaOutput
gpointer driver_private;
GDestroyNotify driver_notify;
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update;
};
struct _MetaCRTC
@ -407,6 +393,7 @@ void meta_monitor_manager_free_output_array (MetaOutput *old_outpu
int n_old_outputs);
void meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes);
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */

View File

@ -20,9 +20,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
@ -311,6 +309,29 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
return NULL;
}
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID output_id)
{
MetaDisplay *display = meta_get_display ();
XRRPropertyInfo *info;
gboolean result = FALSE;
meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
display->atom_hotplug_mode_update);
meta_error_trap_pop (display);
if (info)
{
result = TRUE;
XFree (info);
}
return result;
}
static void
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
{
@ -430,8 +451,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
XRRFreeCrtcInfo (crtc);
}
meta_error_trap_push (meta_get_display ());
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay));
meta_error_trap_pop (meta_get_display ());
n_actual_outputs = 0;
for (i = 0; i < (unsigned)resources->noutput; i++)
@ -484,6 +507,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@ -666,10 +691,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
unsigned int n_outputs)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
MetaDisplay *display = meta_get_display ();
unsigned i;
int width, height, width_mm, height_mm;
meta_display_grab (meta_get_display ());
meta_display_grab (display);
/* First compute the new size of the screen (framebuffer) */
width = 0; height = 0;
@ -763,10 +789,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
*/
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
meta_error_trap_push (meta_get_display ());
meta_error_trap_push (display);
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
width, height, width_mm, height_mm);
meta_error_trap_pop (meta_get_display ());
meta_error_trap_pop (display);
for (i = 0; i < n_crtcs; i++)
{
@ -823,7 +849,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
goto next;
}
meta_error_trap_push (meta_get_display ());
meta_error_trap_push (display);
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
@ -832,7 +858,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
(XID)mode->mode_id,
wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
meta_error_trap_pop (meta_get_display ());
meta_error_trap_pop (display);
if (ok != Success)
{
@ -873,9 +899,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
if (output_info->is_primary)
{
meta_error_trap_push (display);
XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->output_id);
meta_error_trap_pop (display);
}
output_set_presentation_xrandr (manager_xrandr,
@ -901,7 +929,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->is_primary = FALSE;
}
meta_display_ungrab (meta_get_display ());
meta_display_ungrab (display);
}
static void
@ -969,6 +997,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
XRRFreeGamma (gamma);
}
static void
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
}
static gboolean
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
XEvent *event)
@ -978,6 +1016,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
gboolean new_config;
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE;
@ -994,31 +1033,36 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
manager->serial++;
meta_monitor_manager_xrandr_read_current (manager);
/* Check if the current intended configuration has the same outputs
as the new real one, or if the event is a result of an XRandR call.
If so, we can go straight to rebuild the logical config and tell
the outside world.
Otherwise, this event was caused by hotplug, so give a chance to
MetaMonitorConfig.
new_config = manager_xrandr->resources->timestamp >=
manager_xrandr->resources->configTimestamp;
if (meta_monitor_manager_has_hotplug_mode_update (manager))
Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with
new configTimestamps (bug 702804), and the driver may have
changed the EDID for some other reason (old broken qxl and vbox
drivers...).
*/
if (manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp ||
meta_monitor_config_match_current (manager->config, manager))
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
/* Check if the current intended configuration is a result of an
XRandR call. Otherwise, hotplug_mode_update tells us to get
a new preferred mode on hotplug events to handle dynamic
guest resizing. */
if (new_config)
meta_monitor_manager_xrandr_rebuild_derived (manager);
else
meta_monitor_config_make_default (manager->config, manager);
}
else
{
if (!meta_monitor_config_apply_stored (manager->config, manager))
/* Check if the current intended configuration has the same outputs
as the new real one, or if the event is a result of an XRandR call.
If so, we can go straight to rebuild the logical config and tell
the outside world.
Otherwise, this event was caused by hotplug, so give a chance to
MetaMonitorConfig.
Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with new
configTimestamps (bug 702804), and the driver may have changed
the EDID for some other reason (old qxl and vbox drivers). */
if (new_config || meta_monitor_config_match_current (manager->config, manager))
meta_monitor_manager_xrandr_rebuild_derived (manager);
else if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager);
}

View File

@ -20,9 +20,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
@ -36,7 +34,6 @@
#include "util-private.h"
#include <meta/errors.h>
#include "monitor-private.h"
#include "meta-wayland-private.h"
#include "meta-dbus-xrandr.h"
@ -290,7 +287,7 @@ make_logical_config (MetaMonitorManager *manager)
for (j = 0; j < monitor_infos->len; j++)
{
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, i);
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
if (meta_rectangle_equal (&crtc->rect,
&info->rect))
{
@ -358,19 +355,35 @@ make_logical_config (MetaMonitorManager *manager)
static GType
get_default_backend (void)
{
if (meta_is_wayland_compositor ())
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_MONITOR_MANAGER_KMS;
#endif
#if defined(CLUTTER_WINDOWING_X11)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
if (meta_wayland_compositor_is_native (compositor))
return META_TYPE_MONITOR_MANAGER_KMS;
else
/* If we're a Wayland compositor using the X11 backend,
* we're a nested configuration, so return the dummy
* monitor setup. */
if (meta_is_wayland_compositor ())
return META_TYPE_MONITOR_MANAGER;
else
return META_TYPE_MONITOR_MANAGER_XRANDR;
}
else
return META_TYPE_MONITOR_MANAGER_XRANDR;
#endif
#if defined(CLUTTER_WINDOWING_WAYLAND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
{
/* Use the dummy implementation on Wayland for now.
* In the future, we should support wl_fullscreen_output
* which will have CRTC management in the protocol. */
return META_TYPE_MONITOR_MANAGER;
}
#endif
g_assert_not_reached ();
}
static MetaMonitorManager *
@ -614,46 +627,60 @@ static char *
make_display_name (MetaMonitorManager *manager,
MetaOutput *output)
{
char *inches = NULL;
char *vendor_name = NULL;
char *ret;
if (g_str_has_prefix (output->name, "LVDS") ||
g_str_has_prefix (output->name, "eDP"))
return g_strdup (_("Built-in display"));
{
ret = g_strdup (_("Built-in display"));
goto out;
}
if (output->width_mm != -1 && output->height_mm != -1)
if (output->width_mm > 0 && output->height_mm > 0)
{
double d = sqrt (output->width_mm * output->width_mm +
output->height_mm * output->height_mm);
char *inches = diagonal_to_str (d / 25.4);
char *vendor_name;
char *ret;
inches = diagonal_to_str (d / 25.4);
}
if (g_strcmp0 (output->vendor, "unknown") != 0)
{
if (!manager->pnp_ids)
manager->pnp_ids = gnome_pnp_ids_new ();
if (g_strcmp0 (output->vendor, "unknown") != 0)
{
if (!manager->pnp_ids)
manager->pnp_ids = gnome_pnp_ids_new ();
vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids,
output->vendor);
vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids,
output->vendor);
ret = g_strdup_printf ("%s %s", vendor_name, inches);
g_free (vendor_name);
}
else
{
/* TRANSLATORS: this is a monitor name (in case we don't know
the vendor), it's Unknown followed by a size in inches,
like 'Unknown 15"'
*/
ret = g_strdup_printf (_("Unknown %s"), inches);
}
g_free (inches);
return ret;
if (!vendor_name)
vendor_name = g_strdup (output->vendor);
}
else
{
return g_strdup (output->vendor);
if (inches != NULL)
vendor_name = g_strdup (_("Unknown"));
else
vendor_name = g_strdup (_("Unknown Display"));
}
if (inches != NULL)
{
/* TRANSLATORS: this is a monitor vendor name, followed by a
* size in inches, like 'Dell 15"'
*/
ret = g_strdup_printf (_("%s %s"), vendor_name, inches);
}
else
{
ret = g_strdup (vendor_name);
}
out:
g_free (inches);
g_free (vendor_name);
return ret;
}
static gboolean

View File

@ -14,9 +14,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"

View File

@ -19,9 +19,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -47,34 +45,18 @@ northwestcmp (gconstpointer a, gconstpointer b)
{
MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int from_origin_a;
int from_origin_b;
int ax, ay, bx, by;
/* we're interested in the frame position for cascading,
* not meta_window_get_position()
*/
if (aw->frame)
{
ax = aw->frame->rect.x;
ay = aw->frame->rect.y;
}
else
{
ax = aw->rect.x;
ay = aw->rect.y;
}
if (bw->frame)
{
bx = bw->frame->rect.x;
by = bw->frame->rect.y;
}
else
{
bx = bw->rect.x;
by = bw->rect.y;
}
meta_window_get_frame_rect (aw, &a_frame);
meta_window_get_frame_rect (bw, &b_frame);
ax = a_frame.x;
ay = a_frame.y;
bx = b_frame.x;
by = b_frame.y;
/* probably there's a fast good-enough-guess we could use here. */
from_origin_a = sqrt (ax * ax + ay * ay);
@ -90,7 +72,6 @@ northwestcmp (gconstpointer a, gconstpointer b)
static void
find_next_cascade (MetaWindow *window,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
GList *windows,
int x,
@ -102,6 +83,7 @@ find_next_cascade (MetaWindow *window,
GList *sorted;
int cascade_x, cascade_y;
int x_threshold, y_threshold;
MetaRectangle frame_rect;
int window_width, window_height;
int cascade_stage;
MetaRectangle work_area;
@ -120,10 +102,13 @@ find_next_cascade (MetaWindow *window,
* manually cascade.
*/
#define CASCADE_FUZZ 15
if (borders)
if (window->frame)
{
x_threshold = MAX (borders->visible.left, CASCADE_FUZZ);
y_threshold = MAX (borders->visible.top, CASCADE_FUZZ);
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
x_threshold = MAX (borders.visible.left, CASCADE_FUZZ);
y_threshold = MAX (borders.visible.top, CASCADE_FUZZ);
}
else
{
@ -143,30 +128,25 @@ find_next_cascade (MetaWindow *window,
cascade_y = MAX (0, work_area.y);
/* Find first cascade position that's not used. */
window_width = window->frame ? window->frame->rect.width : window->rect.width;
window_height = window->frame ? window->frame->rect.height : window->rect.height;
meta_window_get_frame_rect (window, &frame_rect);
window_width = frame_rect.width;
window_height = frame_rect.height;
cascade_stage = 0;
tmp = sorted;
while (tmp != NULL)
{
MetaWindow *w;
MetaRectangle w_frame_rect;
int wx, wy;
w = tmp->data;
/* we want frame position, not window position */
if (w->frame)
{
wx = w->frame->rect.x;
wy = w->frame->rect.y;
}
else
{
wx = w->rect.x;
wy = w->rect.y;
}
meta_window_get_frame_rect (w, &w_frame_rect);
wx = w_frame_rect.x;
wy = w_frame_rect.y;
if (ABS (wx - cascade_x) < x_threshold &&
ABS (wy - cascade_y) < y_threshold)
@ -223,22 +203,12 @@ find_next_cascade (MetaWindow *window,
g_list_free (sorted);
/* Convert coords to position of window, not position of frame. */
if (borders == NULL)
{
*new_x = cascade_x;
*new_y = cascade_y;
}
else
{
*new_x = cascade_x + borders->visible.left;
*new_y = cascade_y + borders->visible.top;
}
*new_x = cascade_x;
*new_y = cascade_y;
}
static void
find_most_freespace (MetaWindow *window,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
MetaWindow *focus_window,
int x,
@ -250,29 +220,25 @@ find_most_freespace (MetaWindow *window,
int max_area;
int max_width, max_height, left, right, top, bottom;
int left_space, right_space, top_space, bottom_space;
int frame_size_left, frame_size_top;
MetaRectangle work_area;
MetaRectangle avoid;
MetaRectangle outer;
frame_size_left = borders ? borders->visible.left : 0;
frame_size_top = borders ? borders->visible.top : 0;
MetaRectangle frame_rect;
meta_window_get_work_area_current_monitor (focus_window, &work_area);
meta_window_get_outer_rect (focus_window, &avoid);
meta_window_get_outer_rect (window, &outer);
meta_window_get_frame_rect (focus_window, &avoid);
meta_window_get_frame_rect (window, &frame_rect);
/* Find the areas of choosing the various sides of the focus window */
max_width = MIN (avoid.width, outer.width);
max_height = MIN (avoid.height, outer.height);
max_width = MIN (avoid.width, frame_rect.width);
max_height = MIN (avoid.height, frame_rect.height);
left_space = avoid.x - work_area.x;
right_space = work_area.width - (avoid.x + avoid.width - work_area.x);
top_space = avoid.y - work_area.y;
bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y);
left = MIN (left_space, outer.width);
right = MIN (right_space, outer.width);
top = MIN (top_space, outer.height);
bottom = MIN (bottom_space, outer.height);
left = MIN (left_space, frame_rect.width);
right = MIN (right_space, frame_rect.width);
top = MIN (top_space, frame_rect.height);
bottom = MIN (bottom_space, frame_rect.height);
/* Find out which side of the focus_window can show the most of the window */
side = META_LEFT;
@ -304,39 +270,56 @@ find_most_freespace (MetaWindow *window,
switch (side)
{
case META_LEFT:
*new_y = avoid.y + frame_size_top;
if (left_space > outer.width)
*new_x = avoid.x - outer.width + frame_size_left;
*new_y = avoid.y;
if (left_space > frame_rect.width)
*new_x = avoid.x - frame_rect.width;
else
*new_x = work_area.x + frame_size_left;
*new_x = work_area.x;
break;
case META_RIGHT:
*new_y = avoid.y + frame_size_top;
if (right_space > outer.width)
*new_x = avoid.x + avoid.width + frame_size_left;
*new_y = avoid.y;
if (right_space > frame_rect.width)
*new_x = avoid.x + avoid.width;
else
*new_x = work_area.x + work_area.width - outer.width + frame_size_left;
*new_x = work_area.x + work_area.width - frame_rect.width;
break;
case META_TOP:
*new_x = avoid.x + frame_size_left;
if (top_space > outer.height)
*new_y = avoid.y - outer.height + frame_size_top;
*new_x = avoid.x;
if (top_space > frame_rect.height)
*new_y = avoid.y - frame_rect.height;
else
*new_y = work_area.y + frame_size_top;
*new_y = work_area.y;
break;
case META_BOTTOM:
*new_x = avoid.x + frame_size_left;
if (bottom_space > outer.height)
*new_y = avoid.y + avoid.height + frame_size_top;
*new_x = avoid.x;
if (bottom_space > frame_rect.height)
*new_y = avoid.y + avoid.height;
else
*new_y = work_area.y + work_area.height - outer.height + frame_size_top;
*new_y = work_area.y + work_area.height - frame_rect.height;
break;
}
}
static gboolean
window_overlaps_focus_window (MetaWindow *window)
{
MetaWindow *focus_window;
MetaRectangle window_frame, focus_frame, overlap;
focus_window = window->display->focus_window;
if (focus_window == NULL)
return FALSE;
meta_window_get_frame_rect (window, &window_frame);
meta_window_get_frame_rect (focus_window, &focus_frame);
return meta_rectangle_intersect (&window_frame,
&focus_frame,
&overlap);
}
static void
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
MetaFrameBorders *borders,
int *x,
int *y)
{
@ -355,18 +338,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
*/
MetaWindow *focus_window;
MetaRectangle overlap;
focus_window = window->display->focus_window;
/* denied_focus_and_not_transient is only set when focus_window != NULL */
if (window->denied_focus_and_not_transient &&
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
meta_window_same_application (window, focus_window) &&
meta_rectangle_intersect (&window->rect,
&focus_window->rect,
&overlap))
window_overlaps_focus_window (window))
{
find_most_freespace (window, borders, focus_window, *x, *y, x, y);
find_most_freespace (window, focus_window, *x, *y, x, y);
meta_topic (META_DEBUG_PLACEMENT,
"Dialog window %s was denied focus but may be modal "
"to the focus window; had to move it to avoid the "
@ -409,7 +391,7 @@ rectangle_overlaps_some_window (MetaRectangle *rect,
case META_WINDOW_UTILITY:
case META_WINDOW_TOOLBAR:
case META_WINDOW_MENU:
meta_window_get_outer_rect (other, &other_rect);
meta_window_get_frame_rect (other, &other_rect);
if (meta_rectangle_intersect (rect, &other_rect, &dest))
return TRUE;
@ -427,20 +409,14 @@ leftmost_cmp (gconstpointer a, gconstpointer b)
{
MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int ax, bx;
/* we're interested in the frame position for cascading,
* not meta_window_get_position()
*/
if (aw->frame)
ax = aw->frame->rect.x;
else
ax = aw->rect.x;
if (bw->frame)
bx = bw->frame->rect.x;
else
bx = bw->rect.x;
meta_window_get_frame_rect (aw, &a_frame);
meta_window_get_frame_rect (bw, &b_frame);
ax = a_frame.x;
bx = b_frame.x;
if (ax < bx)
return -1;
@ -455,20 +431,14 @@ topmost_cmp (gconstpointer a, gconstpointer b)
{
MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int ay, by;
/* we're interested in the frame position for cascading,
* not meta_window_get_position()
*/
if (aw->frame)
ay = aw->frame->rect.y;
else
ay = aw->rect.y;
if (bw->frame)
by = bw->frame->rect.y;
else
by = bw->rect.y;
meta_window_get_frame_rect (aw, &a_frame);
meta_window_get_frame_rect (bw, &b_frame);
ay = a_frame.y;
by = b_frame.y;
if (ay < by)
return -1;
@ -506,7 +476,6 @@ center_tile_rect_in_area (MetaRectangle *rect,
*/
static gboolean
find_first_fit (MetaWindow *window,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
GList *windows,
int monitor,
@ -540,15 +509,8 @@ find_first_fit (MetaWindow *window,
right_sorted = g_list_copy (windows);
right_sorted = g_list_sort (right_sorted, topmost_cmp);
right_sorted = g_list_sort (right_sorted, leftmost_cmp);
rect.width = window->rect.width;
rect.height = window->rect.height;
if (borders)
{
rect.width += borders->visible.left + borders->visible.right;
rect.height += borders->visible.top + borders->visible.bottom;
}
meta_window_get_frame_rect (window, &rect);
#ifdef WITH_VERBOSE_MODE
{
@ -570,11 +532,6 @@ find_first_fit (MetaWindow *window,
{
*new_x = rect.x;
*new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE;
@ -586,23 +543,18 @@ find_first_fit (MetaWindow *window,
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle outer_rect;
MetaRectangle frame_rect;
meta_window_get_outer_rect (w, &outer_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = outer_rect.x;
rect.y = outer_rect.y + outer_rect.height;
rect.x = frame_rect.x;
rect.y = frame_rect.y + frame_rect.height;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, below_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE;
@ -617,23 +569,18 @@ find_first_fit (MetaWindow *window,
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle outer_rect;
MetaRectangle frame_rect;
meta_window_get_outer_rect (w, &outer_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = outer_rect.x + outer_rect.width;
rect.y = outer_rect.y;
rect.x = frame_rect.x + frame_rect.width;
rect.y = frame_rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, right_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE;
@ -652,7 +599,6 @@ find_first_fit (MetaWindow *window,
void
meta_window_place (MetaWindow *window,
MetaFrameBorders *borders,
int x,
int y,
int *new_x,
@ -661,13 +607,6 @@ meta_window_place (MetaWindow *window,
GList *windows;
const MetaMonitorInfo *xi;
/* frame member variables should NEVER be used in here, only
* MetaFrameBorders. But remember borders == NULL
* for undecorated windows. Also, this function should
* NEVER have side effects other than computing the
* placement coordinates.
*/
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
windows = NULL;
@ -756,7 +695,7 @@ meta_window_place (MetaWindow *window,
{
meta_topic (META_DEBUG_PLACEMENT,
"Not placing window with PPosition or USPosition set\n");
avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y);
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
goto done_no_constraints;
}
}
@ -775,29 +714,27 @@ meta_window_place (MetaWindow *window,
if (parent)
{
int w;
MetaRectangle frame_rect, parent_frame_rect;
meta_window_get_position (parent, &x, &y);
w = parent->rect.width;
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_frame_rect (parent, &parent_frame_rect);
y = parent_frame_rect.y;
/* center of parent */
x = x + w / 2;
x = parent_frame_rect.x + parent_frame_rect.width / 2;
/* center of child over center of parent */
x -= window->rect.width / 2;
x -= frame_rect.width / 2;
/* "visually" center window over parent, leaving twice as
* much space below as on top.
*/
y += (parent->rect.height - window->rect.height)/3;
/* put top of child's frame, not top of child's client */
if (borders)
y += borders->visible.top;
y += (parent_frame_rect.height - frame_rect.height)/3;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
window->desc);
avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y);
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
goto done;
}
@ -813,6 +750,9 @@ meta_window_place (MetaWindow *window,
{
/* Center on current monitor */
int w, h;
MetaRectangle frame_rect;
meta_window_get_frame_rect (window, &frame_rect);
/* Warning, this function is a round trip! */
xi = meta_screen_get_current_monitor_info (window->screen);
@ -820,8 +760,8 @@ meta_window_place (MetaWindow *window,
w = xi->rect.width;
h = xi->rect.height;
x = (w - window->rect.width) / 2;
y = (h - window->rect.height) / 2;
x = (w - frame_rect.width) / 2;
y = (h - frame_rect.height) / 2;
x += xi->rect.x;
y += xi->rect.y;
@ -865,7 +805,7 @@ meta_window_place (MetaWindow *window,
x = xi->rect.x;
y = xi->rect.y;
if (find_first_fit (window, borders, windows,
if (find_first_fit (window, windows,
xi->number,
x, y, &x, &y))
goto done_check_denied_focus;
@ -878,17 +818,17 @@ meta_window_place (MetaWindow *window,
!window->fullscreen)
{
MetaRectangle workarea;
MetaRectangle outer;
MetaRectangle frame_rect;
meta_window_get_work_area_for_monitor (window,
xi->number,
&workarea);
meta_window_get_outer_rect (window, &outer);
meta_window_get_frame_rect (window, &frame_rect);
/* If the window is bigger than the screen, then automaximize. Do NOT
* auto-maximize the directions independently. See #419810.
*/
if (outer.width >= workarea.width && outer.height >= workarea.height)
if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height)
{
window->maximize_horizontally_after_placement = TRUE;
window->maximize_vertically_after_placement = TRUE;
@ -899,7 +839,7 @@ meta_window_place (MetaWindow *window,
* fully overlapping window (e.g. starting multiple terminals)
* */
if (x == xi->rect.x && y == xi->rect.y)
find_next_cascade (window, borders, windows, x, y, &x, &y);
find_next_cascade (window, windows, x, y, &x, &y);
done_check_denied_focus:
/* If the window is being denied focus and isn't a transient of the
@ -909,17 +849,14 @@ meta_window_place (MetaWindow *window,
*/
if (window->denied_focus_and_not_transient)
{
gboolean found_fit;
MetaWindow *focus_window;
MetaRectangle overlap;
gboolean found_fit;
focus_window = window->display->focus_window;
g_assert (focus_window != NULL);
/* No need to do anything if the window doesn't overlap at all */
found_fit = !meta_rectangle_intersect (&window->rect,
&focus_window->rect,
&overlap);
found_fit = !window_overlaps_focus_window (window);
/* Try to do a first fit again, this time only taking into account the
* focus window.
@ -933,7 +870,7 @@ meta_window_place (MetaWindow *window,
x = xi->rect.x;
y = xi->rect.y;
found_fit = find_first_fit (window, borders, focus_window_list,
found_fit = find_first_fit (window, focus_window_list,
xi->number,
x, y, &x, &y);
g_list_free (focus_window_list);
@ -943,7 +880,7 @@ meta_window_place (MetaWindow *window,
* as possible.
*/
if (!found_fit)
find_most_freespace (window, borders, focus_window, x, y, &x, &y);
find_most_freespace (window, focus_window, x, y, &x, &y);
}
done:

View File

@ -16,9 +16,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_PLACE_H
@ -28,7 +26,6 @@
#include "frame.h"
void meta_window_place (MetaWindow *window,
MetaFrameBorders *borders,
int x,
int y,
int *new_x,

View File

@ -17,9 +17,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -59,7 +57,6 @@
#define KEY_OVERLAY_KEY "overlay-key"
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
#define KEY_NO_TAB_POPUP "no-tab-popup"
/* These are the different schemas we are keeping
* a GSettings instance for */
@ -114,8 +111,6 @@ static char **workspace_names = NULL;
static gboolean workspaces_only_on_primary = FALSE;
static gboolean no_tab_popup = FALSE;
static char *iso_next_group_option = NULL;
static void handle_preference_update_enum (GSettings *settings,
@ -367,13 +362,6 @@ static MetaBoolPreference preferences_bool[] =
},
&workspaces_only_on_primary,
},
{
{ KEY_NO_TAB_POPUP,
SCHEMA_MUTTER,
META_PREF_NO_TAB_POPUP,
},
&no_tab_popup,
},
{
{ "auto-maximize",
SCHEMA_MUTTER,
@ -1815,9 +1803,6 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
return "WORKSPACES_ONLY_ON_PRIMARY";
case META_PREF_NO_TAB_POPUP:
return "NO_TAB_POPUP";
case META_PREF_DRAGGABLE_BORDER_WIDTH:
return "DRAGGABLE_BORDER_WIDTH";
@ -1871,7 +1856,7 @@ init_bindings (void)
pref = g_new0 (MetaKeyPref, 1);
pref->name = g_strdup ("overlay-key");
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
pref->builtin = 1;
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
@ -1881,7 +1866,7 @@ static gboolean
update_binding (MetaKeyPref *binding,
gchar **strokes)
{
GSList *old_bindings, *a, *b;
GSList *old_combos, *a, *b;
gboolean changed;
unsigned int keysym;
unsigned int keycode;
@ -1893,8 +1878,8 @@ update_binding (MetaKeyPref *binding,
"Binding \"%s\" has new GSettings value\n",
binding->name);
old_bindings = binding->bindings;
binding->bindings = NULL;
old_combos = binding->combos;
binding->combos = NULL;
for (i = 0; strokes && strokes[i]; i++)
{
@ -1935,17 +1920,17 @@ update_binding (MetaKeyPref *binding,
combo->keysym = keysym;
combo->keycode = keycode;
combo->modifiers = mods;
binding->bindings = g_slist_prepend (binding->bindings, combo);
binding->combos = g_slist_prepend (binding->combos, combo);
meta_topic (META_DEBUG_KEYBINDINGS,
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
binding->name, keysym, keycode, mods);
}
binding->bindings = g_slist_reverse (binding->bindings);
binding->combos = g_slist_reverse (binding->combos);
a = old_bindings;
b = binding->bindings;
a = old_combos;
b = binding->combos;
while (TRUE)
{
if ((!a && b) || (a && !b))
@ -1970,7 +1955,7 @@ update_binding (MetaKeyPref *binding,
}
}
g_slist_free_full (old_bindings, g_free);
g_slist_free_full (old_combos, g_free);
return changed;
}
@ -2105,7 +2090,7 @@ meta_prefs_add_keybinding (const char *name,
pref->name = g_strdup (name);
pref->settings = g_object_ref (settings);
pref->action = action;
pref->bindings = NULL;
pref->combos = NULL;
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
@ -2169,11 +2154,6 @@ meta_prefs_remove_keybinding (const char *name)
return TRUE;
}
/**
* meta_prefs_get_keybindings:
*
* Returns: (element-type MetaKeyPref) (transfer container):
*/
GList *
meta_prefs_get_keybindings ()
{
@ -2261,43 +2241,6 @@ meta_prefs_get_keybinding_action (const char *name)
: META_KEYBINDING_ACTION_NONE;
}
/* This is used by the menu system to decide what key binding
* to display next to an option. We return the first non-disabled
* binding, if any.
*/
void
meta_prefs_get_window_binding (const char *name,
unsigned int *keysym,
MetaVirtualModifier *modifiers)
{
MetaKeyPref *pref = g_hash_table_lookup (key_bindings, name);
if (pref->per_window)
{
GSList *s = pref->bindings;
while (s)
{
MetaKeyCombo *c = s->data;
if (c->keysym != 0 || c->modifiers != 0)
{
*keysym = c->keysym;
*modifiers = c->modifiers;
return;
}
s = s->next;
}
/* Not found; return the disabled value */
*keysym = *modifiers = 0;
return;
}
g_assert_not_reached ();
}
gint
meta_prefs_get_mouse_button_resize (void)
{
@ -2322,25 +2265,6 @@ meta_prefs_get_workspaces_only_on_primary (void)
return workspaces_only_on_primary;
}
gboolean
meta_prefs_get_no_tab_popup (void)
{
return no_tab_popup;
}
void
meta_prefs_set_no_tab_popup (gboolean whether)
{
MetaBasePreference *pref;
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
KEY_NO_TAB_POPUP, &pref))
{
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
}
}
int
meta_prefs_get_draggable_border_width (void)
{

View File

@ -25,9 +25,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_SCREEN_PRIVATE_H
@ -66,8 +64,6 @@ struct _MetaScreen
Visual *default_xvisual;
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
MetaUI *ui;
MetaTabPopup *tab_popup, *ws_popup;
MetaTilePreview *tile_preview;
guint tile_preview_timeout_id;
@ -153,25 +149,9 @@ void meta_screen_foreach_window (MetaScreen *scree
void meta_screen_update_cursor (MetaScreen *screen);
void meta_screen_tab_popup_create (MetaScreen *screen,
MetaTabList list_type,
MetaTabShowType show_type,
MetaWindow *initial_window);
void meta_screen_tab_popup_forward (MetaScreen *screen);
void meta_screen_tab_popup_backward (MetaScreen *screen);
MetaWindow* meta_screen_tab_popup_get_selected (MetaScreen *screen);
void meta_screen_tab_popup_destroy (MetaScreen *screen);
void meta_screen_workspace_popup_create (MetaScreen *screen,
MetaWorkspace *initial_selection);
void meta_screen_workspace_popup_select (MetaScreen *screen,
MetaWorkspace *workspace);
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
void meta_screen_tile_preview_update (MetaScreen *screen,
void meta_screen_update_tile_preview (MetaScreen *screen,
gboolean delay);
void meta_screen_tile_preview_hide (MetaScreen *screen);
void meta_screen_hide_tile_preview (MetaScreen *screen);
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
MetaWindow *not_this_one);
@ -243,7 +223,7 @@ void meta_screen_workspace_switched (MetaScreen *screen,
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
Window meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen);
void meta_screen_create_guard_window (MetaScreen *screen);
gboolean meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent);

View File

@ -19,9 +19,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
@ -45,7 +43,7 @@
#include <meta/compositor.h>
#include "mutter-enum-types.h"
#include "core.h"
#include "meta-wayland-private.h"
#include "meta-wayland.h"
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
@ -310,6 +308,9 @@ set_supported_hint (MetaScreen *screen)
#include <meta/atomnames.h>
#undef item
#undef EWMH_ATOMS_ONLY
screen->display->atom__GTK_FRAME_EXTENTS,
screen->display->atom__GTK_SHOW_WINDOW_MENU,
};
XChangeProperty (screen->display->xdisplay, screen->xroot,
@ -391,6 +392,8 @@ int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
g_return_val_if_fail (index >= 0 && index < screen->n_monitor_infos, -1);
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;
@ -447,17 +450,16 @@ reload_monitor_infos (MetaScreen *screen)
* should effectively be forwarded to events on the background actor,
* providing that the scene graph is set up correctly.
*/
Window
meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen)
static Window
create_guard_window (Display *xdisplay, MetaScreen *screen)
{
XSetWindowAttributes attributes;
Window guard_window;
gulong create_serial;
MetaStackWindow stack_window;
attributes.event_mask = NoEventMask;
attributes.override_redirect = True;
attributes.background_pixel = BlackPixel (xdisplay, screen->number);
/* We have to call record_add() after we have the new window ID,
* so save the serial for the CreateWindow request until then */
@ -470,10 +472,10 @@ meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen)
screen->rect.width,
screen->rect.height,
0, /* border width */
CopyFromParent, /* depth */
CopyFromParent, /* class */
0, /* depth */
InputOnly, /* class */
CopyFromParent, /* visual */
CWEventMask|CWOverrideRedirect|CWBackPixel,
CWEventMask|CWOverrideRedirect,
&attributes);
{
@ -761,10 +763,6 @@ meta_screen_new (MetaDisplay *display,
screen->ui = meta_ui_new (screen->display->xdisplay,
screen->xscreen);
screen->tab_popup = NULL;
screen->ws_popup = NULL;
screen->tile_preview = NULL;
screen->tile_preview_timeout_id = 0;
screen->stack = meta_stack_new (screen);
@ -859,9 +857,9 @@ meta_screen_free (MetaScreen *screen,
screen->wm_sn_selection_window);
if (screen->work_area_later != 0)
g_source_remove (screen->work_area_later);
meta_later_remove (screen->work_area_later);
if (screen->check_fullscreen_later != 0)
g_source_remove (screen->check_fullscreen_later);
meta_later_remove (screen->check_fullscreen_later);
if (screen->monitor_infos)
g_free (screen->monitor_infos);
@ -869,9 +867,6 @@ meta_screen_free (MetaScreen *screen,
if (screen->tile_preview_timeout_id)
g_source_remove (screen->tile_preview_timeout_id);
if (screen->tile_preview)
meta_tile_preview_free (screen->tile_preview);
g_free (screen->screen_name);
g_object_unref (screen);
@ -880,83 +875,34 @@ meta_screen_free (MetaScreen *screen,
meta_display_ungrab (display);
}
typedef struct
void
meta_screen_create_guard_window (MetaScreen *screen)
{
Window xwindow;
XWindowAttributes attrs;
} WindowInfo;
static GList *
list_windows (MetaScreen *screen)
{
Window ignored1, ignored2;
Window *children;
guint n_children, i;
GList *result;
XQueryTree (screen->display->xdisplay,
screen->xroot,
&ignored1, &ignored2, &children, &n_children);
result = NULL;
for (i = 0; i < n_children; ++i)
{
WindowInfo *info = g_new0 (WindowInfo, 1);
meta_error_trap_push_with_return (screen->display);
XGetWindowAttributes (screen->display->xdisplay,
children[i], &info->attrs);
if (meta_error_trap_pop_with_return (screen->display))
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
children[i]);
g_free (info);
}
else
{
info->xwindow = children[i];
}
result = g_list_prepend (result, info);
}
if (children)
XFree (children);
return g_list_reverse (result);
if (screen->guard_window == None)
screen->guard_window = create_guard_window (screen->display->xdisplay, screen);
}
void
meta_screen_manage_all_windows (MetaScreen *screen)
{
GList *windows;
GList *list;
meta_display_grab (screen->display);
if (screen->guard_window == None)
screen->guard_window =
meta_screen_create_guard_window (screen->display->xdisplay, screen);
windows = list_windows (screen);
MetaStackWindow *_children;
MetaStackWindow *children;
int n_children, i;
meta_stack_freeze (screen->stack);
for (list = windows; list != NULL; list = list->next)
meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children);
/* Copy the stack as it will be modified as part of the loop */
children = g_memdup (_children, sizeof (MetaStackWindow) * n_children);
for (i = 0; i < n_children; ++i)
{
WindowInfo *info = list->data;
meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
META_COMP_EFFECT_NONE,
&info->attrs);
meta_window_x11_new (screen->display, children[i].x11.xwindow, TRUE,
META_COMP_EFFECT_NONE);
}
g_free (children);
meta_stack_thaw (screen->stack);
g_list_foreach (windows, (GFunc)g_free, NULL);
g_list_free (windows);
meta_display_ungrab (screen->display);
}
/**
@ -1482,255 +1428,8 @@ meta_screen_update_cursor (MetaScreen *screen)
screen->current_cursor);
}
void
meta_screen_tab_popup_create (MetaScreen *screen,
MetaTabList list_type,
MetaTabShowType show_type,
MetaWindow *initial_selection)
{
MetaTabEntry *entries;
GList *tab_list;
GList *tmp;
int len;
int i;
if (screen->tab_popup)
return;
tab_list = meta_display_get_tab_list (screen->display,
list_type,
screen,
screen->active_workspace);
len = g_list_length (tab_list);
entries = g_new (MetaTabEntry, len + 1);
entries[len].key = NULL;
entries[len].title = NULL;
entries[len].icon = NULL;
i = 0;
tmp = tab_list;
while (i < len)
{
MetaWindow *window;
MetaRectangle r;
window = tmp->data;
entries[i].key = (MetaTabEntryKey) window;
entries[i].title = window->title;
entries[i].icon = g_object_ref (window->icon);
entries[i].blank = FALSE;
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
entries[i].demands_attention = window->wm_state_demands_attention;
if (show_type == META_TAB_SHOW_INSTANTLY ||
!entries[i].hidden ||
!meta_window_get_icon_geometry (window, &r))
meta_window_get_outer_rect (window, &r);
entries[i].rect = r;
/* Find inside of highlight rectangle to be used when window is
* outlined for tabbing. This should be the size of the
* east/west frame, and the size of the south frame, on those
* sides. On the top it should be the size of the south frame
* edge.
*/
#define OUTLINE_WIDTH 5
/* Top side */
if (!entries[i].hidden &&
window->frame && window->frame->bottom_height > 0 &&
window->frame->child_y >= window->frame->bottom_height)
entries[i].inner_rect.y = window->frame->bottom_height;
else
entries[i].inner_rect.y = OUTLINE_WIDTH;
/* Bottom side */
if (!entries[i].hidden &&
window->frame && window->frame->bottom_height != 0)
entries[i].inner_rect.height = r.height
- entries[i].inner_rect.y - window->frame->bottom_height;
else
entries[i].inner_rect.height = r.height
- entries[i].inner_rect.y - OUTLINE_WIDTH;
/* Left side */
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
entries[i].inner_rect.x = window->frame->child_x;
else
entries[i].inner_rect.x = OUTLINE_WIDTH;
/* Right side */
if (!entries[i].hidden &&
window->frame && window->frame->right_width != 0)
entries[i].inner_rect.width = r.width
- entries[i].inner_rect.x - window->frame->right_width;
else
entries[i].inner_rect.width = r.width
- entries[i].inner_rect.x - OUTLINE_WIDTH;
++i;
tmp = tmp->next;
}
if (!meta_prefs_get_no_tab_popup ())
screen->tab_popup = meta_ui_tab_popup_new (entries,
screen->number,
len,
5, /* FIXME */
TRUE);
for (i = 0; i < len; i++)
g_object_unref (entries[i].icon);
g_free (entries);
g_list_free (tab_list);
meta_ui_tab_popup_select (screen->tab_popup,
(MetaTabEntryKey) initial_selection);
if (show_type != META_TAB_SHOW_INSTANTLY)
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
}
void
meta_screen_tab_popup_forward (MetaScreen *screen)
{
g_return_if_fail (screen->tab_popup != NULL);
meta_ui_tab_popup_forward (screen->tab_popup);
}
void
meta_screen_tab_popup_backward (MetaScreen *screen)
{
g_return_if_fail (screen->tab_popup != NULL);
meta_ui_tab_popup_backward (screen->tab_popup);
}
MetaWindow *
meta_screen_tab_popup_get_selected (MetaScreen *screen)
{
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
}
void
meta_screen_tab_popup_destroy (MetaScreen *screen)
{
if (screen->tab_popup)
{
meta_ui_tab_popup_free (screen->tab_popup);
screen->tab_popup = NULL;
}
}
void
meta_screen_workspace_popup_create (MetaScreen *screen,
MetaWorkspace *initial_selection)
{
MetaTabEntry *entries;
int len;
int i;
MetaWorkspaceLayout layout;
int n_workspaces;
int current_workspace;
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
return;
current_workspace = meta_workspace_index (screen->active_workspace);
n_workspaces = meta_screen_get_n_workspaces (screen);
meta_screen_calc_workspace_layout (screen, n_workspaces,
current_workspace, &layout);
len = layout.grid_area;
entries = g_new (MetaTabEntry, len + 1);
entries[len].key = NULL;
entries[len].title = NULL;
entries[len].icon = NULL;
i = 0;
while (i < len)
{
if (layout.grid[i] >= 0)
{
MetaWorkspace *workspace;
workspace = meta_screen_get_workspace_by_index (screen,
layout.grid[i]);
entries[i].key = (MetaTabEntryKey) workspace;
entries[i].title = meta_workspace_get_name (workspace);
entries[i].icon = NULL;
entries[i].blank = FALSE;
g_assert (entries[i].title != NULL);
}
else
{
entries[i].key = NULL;
entries[i].title = NULL;
entries[i].icon = NULL;
entries[i].blank = TRUE;
}
entries[i].hidden = FALSE;
entries[i].demands_attention = FALSE;
++i;
}
screen->ws_popup = meta_ui_tab_popup_new (entries,
screen->number,
len,
layout.cols,
FALSE);
g_free (entries);
meta_screen_free_workspace_layout (&layout);
meta_ui_tab_popup_select (screen->ws_popup,
(MetaTabEntryKey) initial_selection);
meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE);
}
void
meta_screen_workspace_popup_select (MetaScreen *screen,
MetaWorkspace *workspace)
{
g_return_if_fail (screen->ws_popup != NULL);
meta_ui_tab_popup_select (screen->ws_popup,
(MetaTabEntryKey) workspace);
}
MetaWorkspace *
meta_screen_workspace_popup_get_selected (MetaScreen *screen)
{
g_return_val_if_fail (screen->ws_popup != NULL, NULL);
return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup);
}
void
meta_screen_workspace_popup_destroy (MetaScreen *screen)
{
if (screen->ws_popup)
{
meta_ui_tab_popup_free (screen->ws_popup);
screen->ws_popup = NULL;
}
}
static gboolean
meta_screen_tile_preview_update_timeout (gpointer data)
meta_screen_update_tile_preview_timeout (gpointer data)
{
MetaScreen *screen = data;
MetaWindow *window = screen->display->grab_window;
@ -1738,22 +1437,6 @@ meta_screen_tile_preview_update_timeout (gpointer data)
screen->tile_preview_timeout_id = 0;
if (!screen->tile_preview)
{
Window xwindow;
gulong create_serial;
MetaStackWindow stack_window;
screen->tile_preview = meta_tile_preview_new (screen->number);
xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
&create_serial);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
meta_stack_tracker_record_add (screen->stack_tracker,
&stack_window,
create_serial);
}
if (window)
{
switch (window->tile_mode)
@ -1778,12 +1461,16 @@ meta_screen_tile_preview_update_timeout (gpointer data)
if (needs_preview)
{
MetaRectangle tile_rect;
int monitor;
monitor = meta_window_get_current_tile_monitor_number (window);
meta_window_get_current_tile_area (window, &tile_rect);
meta_tile_preview_show (screen->tile_preview, &tile_rect);
meta_compositor_show_tile_preview (screen->display->compositor,
screen, window, &tile_rect, monitor);
}
else
meta_tile_preview_hide (screen->tile_preview);
meta_compositor_hide_tile_preview (screen->display->compositor,
screen);
return FALSE;
}
@ -1791,7 +1478,7 @@ meta_screen_tile_preview_update_timeout (gpointer data)
#define TILE_PREVIEW_TIMEOUT_MS 200
void
meta_screen_tile_preview_update (MetaScreen *screen,
meta_screen_update_tile_preview (MetaScreen *screen,
gboolean delay)
{
if (delay)
@ -1801,7 +1488,7 @@ meta_screen_tile_preview_update (MetaScreen *screen,
screen->tile_preview_timeout_id =
g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
meta_screen_tile_preview_update_timeout,
meta_screen_update_tile_preview_timeout,
screen);
}
else
@ -1809,18 +1496,18 @@ meta_screen_tile_preview_update (MetaScreen *screen,
if (screen->tile_preview_timeout_id > 0)
g_source_remove (screen->tile_preview_timeout_id);
meta_screen_tile_preview_update_timeout ((gpointer)screen);
meta_screen_update_tile_preview_timeout ((gpointer)screen);
}
}
void
meta_screen_tile_preview_hide (MetaScreen *screen)
meta_screen_hide_tile_preview (MetaScreen *screen)
{
if (screen->tile_preview_timeout_id > 0)
g_source_remove (screen->tile_preview_timeout_id);
if (screen->tile_preview)
meta_tile_preview_hide (screen->tile_preview);
meta_compositor_hide_tile_preview (screen->display->compositor,
screen);
}
MetaWindow*
@ -1828,38 +1515,19 @@ meta_screen_get_mouse_window (MetaScreen *screen,
MetaWindow *not_this_one)
{
MetaWindow *window;
Window root_return, child_return;
double root_x_return, root_y_return;
double win_x_return, win_y_return;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
int x, y;
if (not_this_one)
meta_topic (META_DEBUG_FOCUS,
"Focusing mouse window excluding %s\n", not_this_one->desc);
meta_error_trap_push (screen->display);
XIQueryPointer (screen->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
screen->xroot,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&win_x_return,
&win_y_return,
&buttons,
&mods,
&group);
meta_error_trap_pop (screen->display);
free (buttons.mask);
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
&x, &y, NULL);
window = meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
not_this_one,
root_x_return,
root_y_return);
x, y);
return window;
}
@ -1914,7 +1582,7 @@ meta_screen_get_monitor_for_window (MetaScreen *screen,
{
MetaRectangle window_rect;
meta_window_get_outer_rect (window, &window_rect);
meta_window_get_frame_rect (window, &window_rect);
return meta_screen_get_monitor_for_rect (screen, &window_rect);
}
@ -2141,28 +1809,11 @@ meta_screen_get_current_monitor (MetaScreen *screen)
if (screen->display->monitor_cache_invalidated)
{
Window root_return, child_return;
double win_x_return, win_y_return;
double root_x_return, root_y_return;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
int x, y;
XIQueryPointer (screen->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
screen->xroot,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&win_x_return,
&win_y_return,
&buttons,
&mods,
&group);
free (buttons.mask);
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
&x, &y, NULL);
meta_screen_get_current_monitor_for_pos (screen, x, y);
}
return screen->last_monitor_index;

View File

@ -18,9 +18,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>

View File

@ -23,9 +23,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_SESSION_H

View File

@ -29,9 +29,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -1043,7 +1041,7 @@ stack_tracker_event_received (MetaStackTracker *tracker,
if (op->any.serial < tracker->xserver_serial)
{
g_warning ("Spurious X event received affecting stack; doing full re-query");
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;

View File

@ -28,9 +28,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_STACK_TRACKER_H

View File

@ -22,9 +22,7 @@
* 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.
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
@ -92,16 +90,6 @@ meta_stack_new (MetaScreen *screen)
static void
free_last_all_root_children_stacked_cache (MetaStack *stack)
{
unsigned int i;
for (i = 0; i < stack->last_all_root_children_stacked->len; i++)
{
MetaStackWindow *window = &g_array_index (stack->last_all_root_children_stacked, MetaStackWindow, i);
if (window->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND)
g_object_remove_weak_pointer (G_OBJECT (window->wayland.meta_window),
(gpointer *)&window->wayland.meta_window);
}
g_array_free (stack->last_all_root_children_stacked, TRUE);
stack->last_all_root_children_stacked = NULL;
}
@ -1337,17 +1325,6 @@ stack_sync_to_xserver (MetaStack *stack)
/* build XRestackWindows() array from top to bottom */
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_array_append_val (x11_root_children_stacked, top_level_window);
else
{
MetaStackWindow *new;
/* So we can determine later if a cached stack window is
* stale because the corresponding window has been freed we
* associate a weak pointer with the new window. */
new = &g_array_index (all_root_children_stacked, MetaStackWindow, all_root_children_stacked->len - 1);
g_object_add_weak_pointer (G_OBJECT (new->wayland.meta_window),
(gpointer *)&new->wayland.meta_window);
}
}
meta_topic (META_DEBUG_STACK, "\n");
@ -1705,7 +1682,7 @@ window_contains_point (MetaWindow *window,
{
MetaRectangle rect;
meta_window_get_outer_rect (window, &rect);
meta_window_get_frame_rect (window, &rect);
return POINT_IN_RECT (root_x, root_y, rect);
}

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