Compare commits

...

187 Commits

Author SHA1 Message Date
eba848e8aa Bump version to 3.12.0
Update NEWS.
2014-03-25 16:33:00 +01:00
71be7e8493 display: Fix compiler warning
Don't leave a variable uninitialized in case we don't find a matching
surface.
2014-03-25 16:32:22 +01:00
7484d540cd wayland: Use an array initializer for the X server arguments
This fixes the unitialized array members introduced previously and
should avoid such mistakes again going forward.

https://bugzilla.gnome.org/show_bug.cgi?id=727011
2014-03-25 14:52:57 +01:00
a55622d924 wayland: drop -logfile argument
It breaks testing wayland with setuid X server.
2014-03-24 14:18:49 -04:00
1cfaf45389 surface-actor-wayland: Fix meta_surface_actor_wayland_is_argb32
This prevents us from clipping shadows under windows for all
apps, and loads of other fun optimizations.
2014-03-20 18:03:38 -04:00
42491f7724 window: Actually interpret the FRAME_SHAPE_CHANGED result
When I refactored this out into a vfunc, I forgot to change the
code that interprets the result flags to actually respect the
new FRAME_SHAPE_CHANGED result flag.

Since we weren't ever clearing the frame bounds, this meant that
the "shadow clip" wasn't ever updated as a result. Since right now
all Wayland surfaces are considered ARGB32, we always clip shadows
under frames, and thus shadows had this weird "punch-out" from the
first frame shape.
2014-03-20 18:03:35 -04:00
9696e785da screen: Remove flash_window
It's unused as well
2014-03-20 16:48:15 -04:00
0de83ebfb5 display: Remove get_leader_window
It's unused.
2014-03-20 16:46:21 -04:00
337db2a660 window: Kill off the rest of colormaps
I removed the XInstallColormap / XUninstallColormap but forgot
to remove the fields in MetaWindow and the code to set them.
2014-03-20 16:27:22 -04:00
054c307353 window: Remove support for colormaps
While the ICCCM mandates the use of this, it's not necessary under
a composited environment from my understanding, and it's a flat
out no-op under XWayland.

Looking at the other rootless servers like Xwin/Xquartz, it seems
that they contain code for colormap emulation, but they're actually
never used -- a bug prevents the code from ever being called. Given
that it's been this way since 2003, I'm going to hazard a guess that
not many apps using colormaps. Kill them off.
2014-03-20 16:25:09 -04:00
852589897e Move send_icccm_message to window-x11 2014-03-20 16:22:15 -04:00
46b4d6c0f0 Move request_take_focus to window-x11
This will let us kill off send_icccm_message
2014-03-20 16:06:24 -04:00
ab2224686a events: Clean up trailing whitespace 2014-03-20 15:54:16 -04:00
24b08d1a36 Move event handling to a new file
display.c is getting a bit crowded. Move most of the handling
out to another file, events.c.

The long-term goal is to have generic event handling here, with
backend-specific handling for the types of windows and such.
2014-03-20 15:46:32 -04:00
0808adefaf Move focus to be a vfunc 2014-03-20 15:20:15 -04:00
14f424cd02 Move ping to be a vfunc 2014-03-20 15:20:15 -04:00
9debd2fb0d Move delete / kill to be a vfunc 2014-03-20 15:07:44 -04:00
57359da9b4 wayland: Kill the buffer destroy error
Previously, a sequence like this would crash a client:

  => surface.attach(buffer)
  => buffer.destroy()

The correct behavior is to wait until we release the buffer before
destroying it.

  => surface.attach(buffer)
  => surface.attach(buffer2)
  <= buffer.release()
  => buffer.destroy()

The protocol upstream says that "the surface contents are undefined"
in a case like this. Personally, I think that this is broken behavior
and no client should ever do it, so I explicitly killed any client
that tried to do this.

But unfortunately, as we're all well aware, XWayland does this.
Rather than wait for XWayland to be fixed, let's just allow this.

Technically, since we always copy SHM buffers into GL textures, we
could release the buffer as soon as the Cogl texture is made.

Since we do this copy, the semantics we apply are that the texture is
"frozen" in time until another newer buffer is attached. For simple
clients that simply abort on exit and don't wait for the buffer event
anyhow, this has the added bonus that we'll get nice destroy animations.
2014-03-20 13:53:05 -04:00
e67abdd3ff compositor: Kill unused variable 2014-03-20 13:18:55 -04:00
ca4777f778 compositor: Make code a bit more understandable 2014-03-20 13:18:47 -04:00
76dc0ca681 wayland: Exempt CLICKING grab ops when syncing wayland input focus
If we have a CLICKING grab op we still need to send events to xwayland
so that we get them back for gtk+ to process thus we can't steer
wayland input focus away from it.

https://bugzilla.gnome.org/show_bug.cgi?id=726123
2014-03-20 17:08:53 +01:00
8968501031 wayland-seat: Don't send pointer enter/leave events during a GRAB_OP
meta_wayland_seat_repick() can be called in various cases while mutter
has a GRAB_OP ongoing which means we could be sending wrong pointer
enter/leave events.

https://bugzilla.gnome.org/show_bug.cgi?id=726123
2014-03-20 17:08:53 +01:00
1b29113150 wayland: Set/unset wayland focus on mutter grab/ungrab operations
This ensures that we send the proper leave and enter events to wayland
clients.

Particularly, this solves a bug in SSD xwayland windows where clicking
and dragging on the title bar to move the window only works on the odd
turn (unless the pointer moves away from the title bar between
tries). This happens because xwayland gets a button press but doesn't
see the release so when it gets the next button press it discards it
because its pointer button tracking logic says that the button is
already pressed. Sending the proper wayland pointer leave event fixes
it since wayland clients must forget about button state at that point.

https://bugzilla.gnome.org/show_bug.cgi?id=726123
2014-03-20 17:08:53 +01:00
15c59f9919 keybindings: Split out check for filter_keybinding
This is a small code cleanup for clarity.
2014-03-20 11:03:54 -04:00
a53e094fcd window: Move move_resize_internal logic to protocol-specific directories 2014-03-20 11:02:50 -04:00
a377a1a110 window: Move client-type-specific managing / unmanaging to a vfunc 2014-03-20 10:51:32 -04:00
74a1e00e30 window: MetaWindow is now abstract 2014-03-20 10:50:27 -04:00
1c41f71eef window: Add a type for Wayland windows 2014-03-20 10:50:27 -04:00
63350c52cc window: Remove code for static gravity resizes
It was never turned on for all the years it's been there.
2014-03-20 10:50:27 -04:00
56e8c3b625 Bump version to 3.11.92
Update NEWS.
2014-03-19 21:22:46 +01:00
ce3d9fb89f build: Don't try to distribute removed files
Fixes some left-overs from commit ff635bad3b.
2014-03-19 21:09:02 +01:00
27c018ab98 update POTFILES.in
some files were moved from src/core to src/x11

https://bugzilla.gnome.org/show_bug.cgi?id=726683
2014-03-19 21:09:02 +01:00
a1427c7130 Revert "Move MetaGroup to be X11-specific"
This reverts commit f940292cfe.

Turns out MetaGroup was public API and was used by gnome-shell.
Ugh.
2014-03-19 09:12:48 -04:00
91ad92c968 Update .gitignore 2014-03-18 22:08:04 -04:00
f0c7b518e6 Don't generate sources in a subdirectory
This fixes srcdir != builddir issues.
2014-03-18 22:06:31 -04:00
5fa5ace5e6 Move session to x11/
XSMP code is X11-specific, of course.
2014-03-18 22:04:36 -04:00
044c06bff3 Don't include wayland/ by default either 2014-03-18 22:04:36 -04:00
a3ccc4fd1c Remove x11/ directory from default include path 2014-03-18 22:04:36 -04:00
0a20f7458c window: Remove support for _NET_WM_ICON_NAME
We don't seem to use it anywhere.
2014-03-18 22:04:36 -04:00
9c94f8ae47 Move testasyncgetprop.c to x11/ 2014-03-18 22:04:27 -04:00
f940292cfe Move MetaGroup to be X11-specific 2014-03-18 21:23:36 -04:00
48a36356dd window: Make window->desc a bit clearer
And remove the hack for the "broken GNU libc". It works fine on
my system here.
2014-03-18 21:23:34 -04:00
f05983be42 window: Move type_atom to window-x11 2014-03-18 21:15:49 -04:00
dfcefd3315 Remove meta_core_increment_event_serial
It's unused.
2014-03-18 21:12:37 -04:00
3fe755e684 display: Fix a typo 2014-03-18 21:12:37 -04:00
0eb86de807 Move Wayland protocols into src/wayland 2014-03-18 20:37:35 -04:00
ff635bad3b Clean up the source tree
Remove a lot of old, unmaintained files
2014-03-18 20:37:35 -04:00
43a409dec4 window: Don't sync window geometry when we haven't shown it yet 2014-03-18 18:55:32 -04:00
b087fce062 window-actor: Also always assume the plugin manager exists
Addendum to the above...
2014-03-18 18:31:07 -04:00
420f322910 compositor: Assume the plugin manager always exists 2014-03-18 18:25:33 -04:00
4bf6e0ae8c compositor: Kill off an unused cursor variable 2014-03-18 18:25:33 -04:00
97872e70a5 compositor: Fix variable name style in meta_shape_cow_for_window
This has bugged me forever...
2014-03-18 18:25:33 -04:00
be57308663 compositor: Clean up
Remove a bunch of weird checks, random logs, unused variables
and other cruft that nobody cares about today.
2014-03-18 18:25:32 -04:00
33f1bd96f5 compositor: Kill off modal_plugin
We only ever have one plugin, so don't bother recording which plugin
is modal, only whether we are modal or not.
2014-03-18 18:25:32 -04:00
9ba49358e5 compositor: Remove meta_check_end_modal
"This is used when reloading plugins"

Yeah, no.
2014-03-18 18:25:32 -04:00
8b2b65246a Assume the compositor always exists
At one point, it was supported to run mutter without a compositor,
but we don't allow that any longer. A lot of code already assumes
display->compositor exists and doesn't check for a NULL pointer,
so just kill the rest of the checks.
2014-03-18 18:25:32 -04:00
4fdbb466e1 meta-plugin: Remove some unused features
And don't use properties for no reason.
2014-03-18 18:25:31 -04:00
da48b18188 window: Fix build
A bad rebase on top of some other GObject cleanups I had made
this go sour.
2014-03-18 16:45:53 -04:00
a5f1790828 window: Rename wm_hints_urgent to urgent
The flag and setter is now decoupled from the WM_HINTS state.
2014-03-18 15:44:11 -04:00
6efcf2526d window: Move urgency to a setter 2014-03-18 15:44:11 -04:00
d6a27195d3 Move more fields to MetaWindowX11 2014-03-18 15:44:11 -04:00
8f151842fb Start moving X11 implementation to its own subdirectory
This is specifically about managing X11 windows, not necessarily
running as an X11 compositor. By that I mean that this code is
still used for XWayland windows, and event handling is still and
modesetting / monitor management is still in core/.

This is also a fairly conservative move. We don't move anything
like screen.c or bell.c in here, even though those are really
only for X11 clients.
2014-03-18 15:44:11 -04:00
6f7023bc6b Start splitting the X11-specific stuff of MetaWindow out into a subclass
This is fairly simple and basic for now, with just skip_taskbar /
skip_pager, but eventually a lot of "WM policy" like this, including
move-resize, will be in subclasses for each individual surface.
2014-03-18 15:44:11 -04:00
63b158e4da window: Split out recalc of skip_taskbar / skip_pager
This will be our first attempt for the MetaWindowX11Private
2014-03-18 15:44:11 -04:00
b3364cad3e wayland: Update keyboard state unconditionally
In particular we need to know about all key events to keep the xkb
state reliable even if the event is then consumed by a global shortcut
or grab and never reaches any wayland client.

We also need to keep track of all pressed keys at all times so that we
can send an updated set or pressed keys to the focused client when a
grab ends.

https://bugzilla.gnome.org/show_bug.cgi?id=722847
2014-03-18 19:15:17 +01:00
3502cfba34 wayland-keyboard: Split out a function to determine the evdev keycode
We will need to use this is in another place on the next commit.

https://bugzilla.gnome.org/show_bug.cgi?id=722847
2014-03-18 19:15:17 +01:00
5cc6becb63 wayland-keyboard: Make sure we send an updated modifiers event
Any given clutter event carries the modifier state as it was before it
occured but, for the wayland modifiers event, we want the state
including the current event.

To fix this, we'll keep our xkb_state instance around instead of the
serialized mods.

https://bugzilla.gnome.org/show_bug.cgi?id=722847
2014-03-18 19:15:17 +01:00
ae8f21a3dc wayland-keyboard: Don't use our own tracking to detect autorepeat
Clutter already marks all autorepeat key events it as synthetic
key events. We can simply ignore these instead of relying on custom
key tracking code.
2014-03-18 19:15:17 +01:00
0cdf3bd383 Update .gitignore 2014-03-18 13:18:52 -04:00
3de58189c0 window: Remove an unused bit 2014-03-18 13:18:52 -04:00
5270c469a3 window: Remove meta_window_set_gravity as "public" API 2014-03-18 11:24:24 -04:00
7504f16e59 Replace wm_state_modal usage with META_WINDOW_TYPE_DIALOG 2014-03-18 11:24:24 -04:00
cdb7947dd1 window: Remove meta_window_is_modal
It relies on EWMH concepts. Wayland simply has a MODAL_DIALOG type.
2014-03-18 11:24:24 -04:00
cdfc6f5b53 window: Remove vfunc slots for signals
These aren't used currently, and we're going to be adding
more vfuncs.
2014-03-18 11:24:24 -04:00
fcb2ab41b2 window: Remove another bogus comment
It's not referring to anything!
2014-03-18 11:24:16 -04:00
f5bd7c5f50 window: Remove bogus comment
These fields haven't been around for quite some time.
2014-03-18 11:24:16 -04:00
cb549154aa window: Move meta_window_configure_notify to window-x11 2014-03-18 11:24:16 -04:00
ada9610e30 Start hacking out use of xtransient_for
It won't work under Wayland.
2014-03-18 10:25:54 -04:00
f11bf44525 stack: Flatten and simplify the default focus window logic 2014-03-18 10:25:54 -04:00
1f15c85c00 window: Make window_is_terminal private 2014-03-18 10:25:54 -04:00
8b4c5459c0 window: Remove transient_for_as_xid
It's unused, and it exposes an X11-specific property to API.
2014-03-18 10:07:07 -04:00
d07d5d1328 common: remove documentation for dead grab ops 2014-03-17 16:18:11 -04:00
535685742a window: Export is_title_onscreen and shove_title_onscreen as well
This was fixed in the master version of the commit, but I forgot to
squash it on the Wayland branch.
2014-03-17 11:18:26 -04:00
62e45b6d5e wayland-pointer: Drop unused arg from focus grab interface method
https://bugzilla.gnome.org/show_bug.cgi?id=726123
2014-03-17 11:06:58 +01:00
3c6dd5bf6d window: Export a bunch of state flags as accessor methods
This is necessary to reimplement window menus in gnome-shell.
2014-03-15 09:49:56 -04:00
0f85986340 Add a META_MAXIMIZE_BOTH
Which has the value of META_MAXIMIZE_VERTICAL |
META_MAXIMIZE_HORIZONTAL.

This is an obvious code cleanup.
2014-03-15 09:49:56 -04:00
93ac0329db weston-launch: Fix a typo causing mutter-launch to not work 2014-03-14 16:04:56 -04:00
c539dfe0d7 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-14 14:13:05 -04:00
1502d2a79f Revert "hack autogen to allow automake 1.13"
This reverts commit f0c503b5a9.

01:08 < Jasper> desrt, can you revert that mutter-wayland commit for me?
                My laptop with git on it is out of commission.
2014-03-14 01:08:46 -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
124 changed files with 6179 additions and 29282 deletions

19
.gitignore vendored
View File

@ -78,12 +78,12 @@ src/stamp-mutter-marshal.h
src/meta-dbus-xrandr.[ch]
src/meta-dbus-idle-monitor.[ch]
src/mutter-plugins.pc
src/wayland/gtk-shell-protocol.c
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-server-protocol.h
src/gtk-shell-protocol.c
src/gtk-shell-server-protocol.h
src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
doc/reference/*.args
doc/reference/*.bak
doc/reference/*.hierarchy
@ -101,3 +101,10 @@ doc/reference/meta-undocumented.txt
doc/reference/meta-unused.txt
doc/reference/meta-docs.sgml
doc/reference/meta.types
gtk-doc.m4
intltool.m4
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4

View File

@ -1 +0,0 @@
Havoc Pennington <hp@redhat.com>

View File

@ -1,159 +0,0 @@
Metacity Standards Compliance
=============================
$Id$
1) Introduction
2) EWMH Compliance
a. Root Window Properties
b. Root Window Messages
c. Application Window Properties
d. Window Manager Protocols
3) ICCCM Compliance
1) Introduction
---------------
This document details metacity compliance with the relevent standards.
The format of this document is as follows:
[-/+?] Hint Name/Feature Name (Version number)
Errata/Comments
The first character indicates the level of compliance as follows:
- none
/ partial
+ complete
? unknown
The title indicates a feature or a hint in the specification, and the
version number indicates the minimum version of the specification
supported by metacity. Later versions may be supported if no
incompatible changes have been made in the specification.
2) EWMH Compliance
------------------
The EWMH, or Extended Window Manager Hints is a freedesktop.org-
developed standard to support a number of conventions for
communication between the window manager and clients. It builds on
and extends the ICCCM (See Section 3). A copy of the current EWMH
standard is available at http://freedesktop.org/Standards/wm-spec/
a. Root Window Properties
-------------------------
+ _NET_SUPPORTED (1.3)
+ _NET_CLIENT_LIST (1.3)
+ _NET_NUMBER_OF_DESKTOPS (1.3)
+ _NET_DESKTOP_GEOMETRY (1.3)
Metacity does not implement large desktops, so this is kept set to
the screen size.
+ _NET_DESKTOP_VIEWPORT (1.3)
Metacity does not implement viewports, so this is a constant (0,0).
+ _NET_CURRENT_DESKTOP (1.3)
+ _NET_DESKTOP_NAMES (1.3)
+ _NET_ACTIVE_WINDOW (1.3)
+ _NET_WORKAREA (1.3)
+ _NET_SUPPORTING_WM_CHECK (1.3)
+ _NET_VIRTUAL_ROOTS (1.3)
Metacity does not read or set this property, but it does not use
virtual roots to implement virtual desktops, so it complies with the
specification.
+ _NET_DESKTOP_LAYOUT (1.3)
+ _NET_SHOWING_DESKTOP (1.3)
b. Root Window Messages
-----------------------
+ _NET_CLOSE_WINDOW (1.3)
- _NET_MOVERESIZE_WINDOW (1.3)
Metacity supports this message, but the specification is unclear on
the layout of the detail value, and as such it is #if 0'd in the code
+ _NET_WM_MOVERESIZE (1.3)
- _NET_RESTACK_WINDOW (1.3)
Metacity will raise or lower windows in response to this message,
but the sibling restack modes are not supported, and it is currently
#if 0'd in the code.
+ _NET_REQUEST_FRAME_EXTENTS (1.3)
c. Application Window Properties
--------------------------------
+ _NET_WM_NAME (1.3)
+ _NET_WM_VISIBLE_NAME (1.3)
Metacity does not set this property, but metacity will never display
a name different from _NET_WM_NAME
+ _NET_WM_ICON_NAME (1.3)
+ _NET_WM_VISIBLE_ICON_NAME (1.3)
Metacity does not set this property, but metacity will never display
a name different from _NET_WM_NAME
+ _NET_WM_DESKTOP (1.3)
+ _NET_WM_WINDOW_TYPE (1.3)
/ _NET_WM_STATE (1.3)
This property is read and updated according to the specification,
but see caveat below.
Metacity does not recognize separate vertical and horizontal
maximization states. Currently metacity will do a two-dimensional
maximization if either property is set.
See: http://bugzilla.gnome.org/show_bug.cgi?id=113601
Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is
unimplemented.
+ _NET_WM_ALLOWED_ACTIONS (1.3)
Metacity keeps this hint up to date. The code is somewhat crufty
and should be rewritten, though it is functional.
See: http://bugzilla.gnome.org/show_bug.cgi?id=90420
+ _NET_WM_STRUT (1.3)
+ _NET_WM_STRUT_PARTIAL (1.3)
+ _NET_WM_ICON_GEOMETRY (1.3)
Metacity uses this property to draw minimize/restore animations
+ _NET_WM_ICON (1.3)
+ _NET_WM_PID (1.3)
+ _NET_WM_HANDLED_ICONS (1.3)
Metacity does not read or set this property. However, metacity
never manages iconified windows, and so has no need to do so.
+ _NET_WM_USER_TIME (1.3)
Metacity uses this property to prevent applications from stealing
focus if supported by the toolkit.
+ _NET_FRAME_EXTENTS (1.3)
If set in response to a _NET_REQUEST_FRAME_EXTENTS message received
prior to the window being mapped, this may be an estimate. This is,
however, expressly allowed by the specification.
d. Window Manager Protocols
---------------------------
+ _NET_WM_PING (1.3)
3) ICCCM Compliance
-------------------
TODO

15414
ChangeLog

File diff suppressed because it is too large Load Diff

1297
Doxyfile

File diff suppressed because it is too large Load Diff

298
HACKING
View File

@ -1,298 +0,0 @@
Intro...
Window managers have a few ways in which they are significantly different
from other applications. This file, combined with the code overview in
doc/code-overview.txt, should hopefully provide a series of relatively
quick pointers (hopefully only a few minutes each) to some of the places
one can look to orient themselves and get started. Some of this will be
general to window managers on X, much will be specific to Metacity, and
there's probably some information that's common to programs in general but
is nonetheless useful.
Overview
Administrative issues
Minimal Building/Testing Environment
Relevant standards and X properties
Debugging and testing
Debugging logs
Adding information to the log
Valgrind
Testing Utilities
Technical gotchas to keep in mind
Other important reading
Extra reading
Ideas for tasks to work on
Administrative issues
Don't commit substantive code in here without asking hp@redhat.com.
Adding translations, no-brainer typo fixes, etc. is fine.
The code could use cleanup in a lot of places, feel free to do so.
See http://developer.gnome.org/dotplan/for_maintainers.html for
information on how to make a release. The only difference from those
instructions is that the minor version number of a Metacity release
should always be a number from the Fibonacci sequence.
Minimal Building/Testing Environment
You do not need to _install_ a development version of Metacity to
build, run and test it; you can run it from some temporary
directory. Also, you do not need to build all of Gnome in order to
build a development version of Metacity -- odds are, you may be able
to build metacity from CVS without building any other modules.
As long as you have gtk+ >= 3.0 and GIO >= 2.25.10 with your distro
(gtk+ >= 2.6 if you manually revert the change from bug 348633), you
should be able to install your distro's development packages
(e.g. gtk2-devel, glib-devel, startup-notification-devel on
Fedora; also, remember to install the gnome-common package which is
needed for building cvs versions of Gnome modules like Metacity) as
well as the standard development tools (gcc, autoconf, automake,
pkg-config, intltool, and libtool) and be ready to build and test
Metacity. Steps to do so:
$ svn checkout http://svn.gnome.org/svn/metacity/trunk metacity
$ cd metacity
$ ./autogen.sh --prefix /usr
$ make
$ ./src/metacity --replace
Again, note that you do not need to run 'make install'.
Relevant standards and X properties
There are two documents that describe some basics about how window
managers should behave: the ICCCM (Inter-Client Communication Conventions
Manual) and EWMH (Extended Window Manager Hints). You can find these at
the following locations:
ICCCM - http://tronche.com/gui/x/icccm/
EWMH - :pserver:anoncvs@pdx.freedesktop.org:/cvs
The ICCCM is usually available in RPM or DEB format as well. There is
actually an online version of the EWMH, but it is almost always woefully
out of date. Just get it from cvs with these commands (the backslash
means include the stuff from the next line):
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions login
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions \
checkout wm-spec
DO NOT GO AND READ THOSE THINGS. THEY ARE REALLY, REALLY BORING.
If you do, you'll probably end up catching up on your sleep instead of
hacking on Metacity. ;-) Instead, just look at the table of contents and
glance at a page or two to get an idea of what's in there. Then only
refer to it if you see something weird in the code and you don't know
what it is but has some funny looking name like you see in one of those
two documents.
You can refer to the COMPLIANCE file for additional information on these
specifications and Metacity's compliance therewith.
One of the major things those documents cover that are useful to learn
about immediately are X properties. The right way to learn about those,
though, is through hand on experimentation with the xprop command (and
then look up things you find from xprop in those two manuals if you're
curious enough). First, try running
xprop
in a terminal and click on one of the windows on your screen. That gives
you the x properties for that window. Look through them and get a basic
idea of what's there for kicks. Note that you can get rid of some of the
verboseness by grepping out the _NET_WM_ICON stuff, i.e.
xprop | grep -v _NET_WM_ICON
Next, try running
xprop -root
in a terminal. There's all the properties of the root window (which you
can think of as the "main" Xserver window). You can also manually
specify individual windows that you want the properties of with
xprop -id <id>
if you know the id of the window in question. You can get the id of a
given window by either running xwininfo, e.g.
xwininfo | grep "Window id" | cut -f 4 -d ' '
or by looking at the _NET_CLIENT_STACKING property of the root
window. Finally, it can also be useful to add "-spy" (without the
quotes) to the xprop command to get it to continually monitor that
window and report any changes to you.
Debugging information
Trying to run a window manager under a typical debugger, such as gdb,
unfortunately just doesn't work very well. So, we have to resort to
other methods.
Debugging logs
First, note that you can start a new version of metacity to replace the
existing one by running
metacity --replace
(which also comes in handy in the form "./src/metacity --replace" when
trying to quickly test a small change while hacking on metacity without
doing a full "make install", though I'm going off topic...) This will
allow you to see any warnings printed at the terminal. Sometimes it's
useful to have these directed to a logfile instead, which you can do by
running
METACITY_USE_LOGFILE=1 metacity --replace
The logfile it uses will be printed in the terminal. Sometimes, it's
useful to get more information than just warnings. You can set
METACITY_VERBOSE to do that, like so:
METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 metacity --replace
(note that METACITY_VERBOSE=1 can be problematic without
METACITY_USE_LOGFILE=1; avoid it unless running in from something that
won't be managed by the new Metacity--see bug 305091 for more details).
There are also other flags, such as METACITY_DEBUG, most of which I
haven't tried and don't know what they do. Go to the source code
directory and run
grep "METACITY_" * | grep getenv
to find out what the other ones are.
Adding information to the log
Since we can't single step with a debugger, we often have to fall back to
the primitive method of getting information we want to know: adding
"print" statements. Metacity has a fairly structured way to do this,
using the functions meta_warning, meta_topic, and meta_verbose. All
three have the same basic format as printf, except that meta_topic also
takes a leading enumeration parameter to specify the type of message
being shown (makes it easier for grepping in a verbose log). You'll find
tons of examples in the source code if you need them; just do a quick
grep or look in most any file. Note that meta_topic and meta_verbose
messages only appear if verbosity is turned on. I tend to frequently add
temporary meta_warning statements (or switch meta_topic or meta_verbose
ones to meta_warning ones) and then undo the changes once I've learned
the info that I needed.
There is also a meta_print_backtrace (which again is only active if
verbosity is turned on) that can also be useful if you want to learn how
a particular line of code gets called. And, of course, there's always
g_assert if you want to make sure some section isn't executed (or isn't
executed under certain conditions).
Valgrind
Valgrind is awesome for finding memory leaks or corruption and
uninitialized variables. But I also tend to use it in a non-traditional
way as a partial substitute for a normal debugger: it can provide me with
a stack trace of where metacity is crashing if I made a change that
caused it to do so, which is one of the major uses of debuggers. (And,
what makes it cooler than a debugger is that there will also often be
warnings pinpointing the cause of the crash from either some kind of
simple memory corruption or an uninitialized variable). Sometimes, when
I merely want to know what is calling a particular function I'll just
throw in an "int i; printf("%d\n", i);" just because valgrind will give
me a full stacktrace whenever it sees that uninitialized variable being
used (yes, I could use meta_print_backtrace, but that means I have to
turn verbosity on).
To run metacity under valgrind, use options typical for any Gnome
program, such as
valgrind --log-file=metacity.log --tool=memcheck --num-callers=48 \
--leak-check=yes --leak-resolution=high --show-reachable=yes \
./src/metacity --replace
where, again, the backslashes mean to join all the stuff on the following
line with the previous one.
However, there is a downside. Things run a little bit slowly, and it
appears that you'll need about 1.5GB of ram, which unfortunately prevents
most people from trying this.
Testing Utilities
src/run-metacity.sh
The script src/run-metacity.sh is useful to hack on the window manager.
It runs metacity in an Xnest. e.g.:
CLIENTS=3 ./run-metacity.sh
or
DEBUG=memprof ./run-metacity.sh
or
DEBUG_TEST=1 ./run-metacity-sh
or whatever.
metacity-message
The tool metacity-message can be used as follows:
metacity-message reload-theme
metacity-message restart
metacity-message enable-keybindings
metacity-message disable-keybindings
The first of these is useful for testing themes, the second is just
another way (besides the --restart flag to metacity itself) of
restarting metacity, and the third is useful for testing Metacity when
running it under an Xnest (typically, the Metacity under the Xnest
wouldn't get keybinding notifications--making keyboard navigation not
work--but if you disable the keybindings for the global Metacity then
the Metacity under the Xnest can then get those keybinding notifications).
metacity-window-demo
metacity-window-demo is good for trying behavior of various kinds
of window without launching a full desktop.
Technical gotchas to keep in mind
Files that include gdk.h or gtk.h are not supposed to include
display.h or window.h or other core files. Files in the core
(display.[hc], window.[hc]) are not supposed to include gdk.h or
gtk.h. Reasons:
"Basically you don't want GDK most of the time. It adds
abstractions that cause problems, because they aren't designed to
be used in a WM where we do weird stuff (display grabs, and just
being the WM). At best GDK adds inefficiency, at worst it breaks
things in weird ways where you have to be a GDK guru to figure
them out. Owen also told me that they didn't want to start adding
a lot of hacks to GDK to let a WM use it; we both agreed back in
the mists of time that metacity would only use it for the "UI"
bits as it does.
Having the split in the source code contains and makes very clear
the interface between the WM and GDK/GTK. This keeps people from
introducing extra GDK/GTK usage when it isn't needed or
appropriate. Also, it speeds up the compilation a bit, though this
was perhaps more relevant 5 years ago than it is now.
There was also a very old worry that the GDK stuff might have to
be in a separate process to work right; that turned out to be
untrue. Though who knows what issues the CM will introduce."
Remember that strings stored in X properties are not in UTF-8, and they
have to end up in UTF-8 before we try putting them through Pango.
If you make any X request involving a client window, you have to
meta_error_trap_push() around the call; this is not necessary for X
requests on the frame windows.
Remember that not all windows have frames, and window->frame can be NULL.
Other important reading & where to get started
Extra reading
There are some other important things to read to get oriented as well.
These are:
http://pobox.com/~hp/features.html
rationales.txt
doc/code-overview.txt
It pays to read http://pobox.com/~hp/features.html in order
to understand the philosophy of Metacity.
The rationales.txt file has two things: (1) a list of design choices with
links in the form of bugzilla bugs that discuss the issue, and (2) a list
outstanding bug categories, each of which is tracked by a particular
tracker bug in bugzilla from which you can find several closely related
bug reports.
doc/code-overview.txt provides a fairly good overview of the code,
including coverage of the function of the various files, the main
structures and their relationships, and places to start looking in the
code tailored to general categories of tasks.
Ideas for tasks to work on
There are a variety of things you could work on in the code. You may
have ideas of your own, but in case you don't, let me provide a list of
ideas you could choose from:
If you're ambitious, there's a list of things Havoc made that he'd really
like to see tackled, which you can find at
http://log.ometer.com/2004-05.html. Be sure to double check with someone
to make sure the item is still relevant if you're interested in one of
these. Another place to look for ideas, of course, is bugzilla. One can
just do queries and look for things that look fixable.
However, perhaps the best way of getting ideas of related tasks to work
on, is to look at the second half of the rationales.txt file, which tries
to group bugs by type.

View File

@ -1,8 +0,0 @@
Tomas Frydrych
Email: tf linux intel com
Userid: tomasf
Owen Taylor
Email: otaylor redhat com
Userid: otaylor

View File

@ -1,43 +0,0 @@
Currently active maintainers
--------------------------------
Elijah Newren
Email: newren gmail com
Userid: newren
- Usually won't touch the theme bugs (isn't interested) or the
compositor (until open source nvidia drivers are up to snuff).
Tends to be most interested in libwnck/gtk interactions, focus
issues, constraints problems, and raising/stacking, but works on
just about anything other than themes and the compositor.
Thomas Thurman
Email: thomas thurman org uk
Userid: tthurman
- Responsible for all theme bugs and the compositor (thank goodness
Thomas got involved, eh?). I'm sure he'll replace this sentence
with his interests when he reads it. ;-)
Semi-active maintainers
--------------------------------
Havoc Pennington
Email: hp redhat com
Userid: hp
- Original author. Doesn't patch metacity anymore, but is active in
answering questions, responding to bugs, providing very helpful
suggestions and insight, and even assisting with debugging.
Important historical figureheads
--------------------------------
Rob Adams (readams readams net)
- Was the main maintainer of metacity for a while; particular areas
of focus included xinerama, placement, and an older version of the
constraints code. Still responds to bugs every once in a while.
Søren Sandmann (sandmann redhat com)
- Wrote most of the current compositing manager code + libcm

View File

@ -1,7 +1,5 @@
SUBDIRS=src protocol po doc
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
SUBDIRS=src po doc
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache

33
NEWS
View File

@ -1,3 +1,36 @@
3.12.0
======
* Fix grab issue with SSD xwayland windows [Rui; #726123]
* Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011]
Contributors:
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode
3.11.92
=======
* Fix identification of CSD windows [Owen; #723029]
* Update keyboard state unconditionally [Rui; #722847]
* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan,
Jasper, Marek, Florian; #723580, #726123, #726683]
Contributors:
Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie,
Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
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]

416
README
View File

@ -1,416 +0,0 @@
The original codebase named "Metacity" is not a meta-City as in an
urban center, but rather Meta-ness as in the state of being
meta. i.e. metacity : meta as opacity : opaque. Also it may have
something to do with the Meta key on UNIX keyboards.
Since then, it has been renamed mutter after a rebase on top of
clutter as a compositing manager.
COMPILING MUTTER
===
You need GTK+ 2.2. For startup notification to work you need
libstartup-notification at
http://www.freedesktop.org/software/startup-notification/ or on the
GNOME ftp site.
You need Clutter 1.0. You need gobject-introspection 0.6.3.
REPORTING BUGS AND SUBMITTING PATCHES
===
Report new bugs on http://bugzilla.gnome.org. Please check for
duplicates, *especially* if you are reporting a feature request.
Please do *not* add "me too!" or "yes I really want this!" comments to
feature requests in bugzilla. Please read
http://pobox.com/~hp/features.html prior to adding any kind of flame
about missing features or misfeatures.
Feel free to send patches too; Metacity is relatively small and
simple, so if you find a bug or want to add a feature it should be
pretty easy. Send me mail, or put the patch in bugzilla.
See the HACKING file for some notes on hacking Mutter.
MUTTER FEATURES
===
- Uses GTK+ 2.0 for drawing window frames. This means colors, fonts,
etc. come from GTK+ theme.
- Does not expose the concept of "window manager" to the user. Some
of the features in the GNOME control panel and other parts of the
desktop happen to be implemented in metacity, such as changing your
window border theme, or changing your window navigation shortcuts,
but the user doesn't need to know this.
- Includes only the window manager; does not try to be a desktop
environment. The pager, configuration, etc. are all separate and
modular. The "libwnck" library (which I also wrote) is available
for writing metacity extensions, pagers, and so on. (But libwnck
isn't metacity specific, or GNOME-dependent; it requires only GTK,
and should work with KWin, fvwm2, and other EWMH-compliant WMs.)
- Has a simple theme system and a couple of extra themes come with it.
Change themes via gsettings:
gsettings set org.gnome.desktop.wm.preferences theme Crux
gsettings set org.gnome.desktop.wm.preferences theme Gorilla
gsettings set org.gnome.desktop.wm.preferences theme Atlanta
gsettings set org.gnome.desktop.wm.preferences theme Bright
See theme-format.txt for docs on the theme format. Use
metacity-theme-viewer to preview themes.
- Change number of workspaces via gsettings:
gsettings set org.gnome.desktop.wm.preferences num-workspaces 5
Can also change workspaces from GNOME 2 pager.
- Change focus mode:
gsettings set org.gnome.desktop.wm.preferences focus-mode mouse
gsettings set org.gnome.desktop.wm.preferences focus-mode sloppy
gsettings set org.gnome.desktop.wm.preferences focus-mode click
- Global keybinding defaults include:
Alt-Tab forward cycle window focus
Alt-Shift-Tab backward cycle focus
Alt-Ctrl-Tab forward cycle focus among panels
Alt-Ctrl-Shift-Tab backward cycle focus among panels
Alt-Escape cycle window focus without a popup thingy
Ctrl-Alt-Left Arrow previous workspace
Ctrl-Alt-Right Arrow next workspace
Ctrl-Alt-D minimize/unminimize all, to show desktop
Change keybindings for example:
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]'
Also try the GNOME keyboard shortcuts control panel.
- Window keybindings:
Alt-space window menu
Mnemonics work in the menu. That is, Alt-space then underlined
letter in the menu item works.
Choose Move from menu, and arrow keys to move the window.
While moving, hold down Control to move slower, and
Shift to snap to edges.
Choose Resize from menu, and nothing happens yet, but
eventually I might implement something.
Keybindings for things like maximize window, vertical maximize,
etc. can be bound, but may not all exist by default. See
metacity.schemas.
- Window mouse bindings:
Clicking anywhere on frame with button 1 will raise/focus window
If you click a window control, such as the close button, then the
control will activate on button release if you are still over it
on release (as with most GUI toolkits)
If you click and drag borders with button 1 it resizes the window
If you click and drag the titlebar with button 1 it moves the
window.
If you click anywhere on the frame with button 2 it lowers the
window.
If you click anywhere on the frame with button 3 it shows the
window menu.
If you hold down Super (windows key) and click inside a window, it
will move the window (buttons 1 and 2) or show menu (button 3).
Or you can configure a different modifier for this.
If you pick up a window with button 1 and then switch workspaces
the window will come with you to the new workspace, this is
a feature copied from Enlightenment.
If you hold down Shift while moving a window, the window snaps
to edges of other windows and the screen.
- Session management:
Mutter connects to the session manager and will set itself up to
be respawned. It theoretically restores sizes/positions/workspace
for session-aware applications.
- Mutter implements much of the EWMH window manager specification
from freedesktop.org, as well as the older ICCCM. Please refer to
the COMPLIANCE file for information on mutter compliance with
these standards.
- Uses Pango to render text, so has cool i18n capabilities.
Supports UTF-8 window titles and such.
- There are simple animations for actions such as minimization,
to help users see what is happening. Should probably
have a few more of these and make them nicer.
- if you have the proper X setup, set the GDK_USE_XFT=1
environment variable to get antialiased window titles.
- considers the panel when placing windows and maximizing
them.
- handles the window manager selection from the ICCCM. Will exit if
another WM claims it, and can claim it from another WM if you pass
the --replace argument. So if you're running another
ICCCM-compliant WM, you can run "mutter --replace" to replace it
with Metacity.
- does basic colormap handling
- and much more! well, maybe not a lot more.
HOW TO ADD EXTERNAL FEATURES
===
You can write a mutter "plugin" such as a pager, window list, icon
box, task menu, or even things like "window matching" using the
Extended Window Manager Hints. See http://www.freedesktop.org for the
EWMH specification. An easy-to-use library called "libwnck" is
available that uses the EWMH and is specifically designed for writing
WM accessories.
You might be interested in existing accessories such as "Devil's Pie"
by Ross Burton, which add features to Mutter (or other
EWMH-compliant WMs).
MUTTER BUGS, NON-FEATURES, AND CAVEATS
===
See bugzilla: http://bugzilla.gnome.org/query.cgi
FAQ
===
Q: Will you add my feature?
A: If it makes sense to turn on unconditionally, or is genuinely a
harmless preference that I would not be embarrassed to put in a
simple, uncluttered, user-friendly configuration dialog.
If the only rationale for your feature is that other window
managers have it, or that you are personally used to it, or
something like that, then I will not be impressed. Metacity is
firmly in the "choose good defaults" camp rather than the "offer 6
equally broken ways to do it, and let the user pick one" camp.
This is part of a "no crackrock" policy, despite some exceptions
I'm mildly embarrassed about. For example, multiple workspaces
probably constitute crackrock, they confuse most users and really
are not that useful if you have a decent tasklist and so on. But I
am too used to them to turn them off. Or alternatively
iconification/tasklist is crack, and workspaces/pager are good. But
having both is certainly a bit wrong. Sloppy focus is probably
crackrock too.
But don't think unlimited crack is OK just because I slipped up a
little. No slippery slope here.
Don't let this discourage patches and fixes - I love those. ;-)
Just be prepared to hear the above objections if your patch adds
some crack-ridden configuration option.
http://pobox.com/~hp/free-software-ui.html
http://pobox.com/~hp/features.html
Q: Will Mutter be part of GNOME?
A: It is not officially part of GNOME as of GNOME 2.27. We are
hoping to have mutter officially included as of GNOME 2.28.
Q: Why does Mutter remember the workspace/position of some apps
but not others across logout/login?
A: Mutter only stores sizes/positions for apps that are session
managed. As far as I can determine, there is no way to attempt to
remember workspace/position for non-session-aware apps without
causing a lot of weird effects.
The reason is that you don't know which non-SM-aware apps were
launched by the session. When you initially log in, Metacity sees a
bunch of new windows appear. But it can't distinguish between
windows that were stored in your session, or windows you just
launched after logging in. If Metacity tried to guess that a window
was from the session, it could e.g. end up maximizing a dialog, or
put a window you just launched on another desktop or in a weird
place. And in fact I see a lot of bugs like this in window managers
that try to handle non-session-aware apps.
However, for session-aware apps, Mutter can tell that the
application instance is from the session and thus restore it
reliably, assuming the app properly restores the windows it had
open on session save.
So the correct way to fix the situation is to make apps
session-aware. libSM has come with X for years, it's very
standardized, it's shared by GNOME and KDE - even twm is
session-aware. So anyone who won't take a patch to add SM is more
archaic than twm - and you should flame them. ;-)
Docs on session management:
http://www.fifi.org/doc/xspecs/xsmp.txt.gz
http://www.fifi.org/doc/xspecs/SMlib.txt.gz
See also the ICCCM section on SM. For GNOME apps, use the
GnomeClient object. For a simple example of using libSM directly,
twm/session.c in the twm source code is pretty easy to understand.
Q: How about adding viewports in addition to workspaces?
A: I could conceivably be convinced to use viewports _instead_ of
workspaces, though currently I'm not thinking that. But I don't
think it makes any sense to have both; it's just confusing. They
are functionally equivalent.
You may think this means that you won't have certain keybindings,
or something like that. This is a misconception. The only
_fundamental_ difference between viewports and workspaces is that
with viewports, windows can "overlap" and appear partially on
one and partially on another. All other differences that
traditionally exist in other window managers are accidental -
the features commonly associated with viewports can be implemented
for workspaces, and vice versa.
So I don't want to have two kinds of
workspace/desktop/viewport/whatever, but I'm willing to add
features traditionally associated with either kind if those
features make sense.
Q: Why is the panel always on top?
A: Because it's a better user interface, and until we made this not
configurable a bunch of apps were not getting fixed (the app
authors were just saying "put your panel on the bottom" instead of
properly supporting fullscreen mode, and such).
rationales.txt has the bugzilla URL for some flamefesting on this,
if you want to go back and relive the glory.
Read these and the bugzilla stuff before asking/commenting:
http://pobox.com/~hp/free-software-ui.html
http://pobox.com/~hp/features.html
Q: Why is there no edge flipping?
A: This one is also in rationales.txt. Because "ouija board" UI, where
you just move the mouse around and the computer guesses what you
mean, has a lot of issues. This includes mouse focus, shade-hover
mode, edge flipping, autoraise, etc. Metacity has mouse focus and
autoraise as a compromise, but these features are all confusing for
many users, and cause problems with accessibility, fitt's law, and
so on.
Read these and the bugzilla stuff before asking/commenting:
http://pobox.com/~hp/free-software-ui.html
http://pobox.com/~hp/features.html
Q: Why does wireframe move/resize suck?
A: You can turn it on with the reduced_resources setting.
But: it has low usability, and is a pain
to implement, and there's no reason opaque move/resize should be a
problem on any setup that can run a modern desktop worth a darn to
begin with.
Read these and the bugzilla stuff before asking/commenting:
http://pobox.com/~hp/free-software-ui.html
http://pobox.com/~hp/features.html
The reason we had to add wireframe anyway was broken
proprietary apps that can't handle lots of resize events.
Q: Why no XYZ?
A: You are probably getting the idea by now - check rationales.txt,
query/search bugzilla, and read http://pobox.com/~hp/features.html
and http://pobox.com/~hp/free-software-ui.html
Then sit down and answer the question for yourself. Is the feature
good? What's the rationale for it? Answer "why" not just "why not."
Justify in terms of users as a whole, not just users like
yourself. How else can you solve the same problem? etc. If that
leads you to a strong opinion, then please, post the rationale for
discussion to an appropriate bugzilla bug, or to
usability@gnome.org.
Please don't just "me too!" on bugzilla bugs, please don't think
flames will get you anywhere, and please don't repeat rationale
that's already been offered.
Q: Your dumb web pages you made me read talk about solving problems in
fundamental ways instead of adding preferences or workarounds.
What are some examples where metacity has done this?
A: There are quite a few, though many opportunities remain. Sometimes
the real fix involves application changes. The metacity approach is
that it's OK to require apps to change, though there are also
plenty of workarounds in metacity for battles considered too hard
to fight.
Here are some examples:
- fullscreen mode was introduced to allow position constraints,
panel-on-top, and other such things to apply to normal windows
while still allowing video players etc. to "just work"
- "whether to include minimized windows in Alt+Tab" was solved
by putting minimized windows at the *end* of the tab order.
- Whether to pop up a feedback display during Alt+Tab was solved by
having both Alt+Tab and Alt+Esc
- Whether to have a "kill" feature was solved by automatically
detecting and offering to kill stuck apps. Better, metacity
actually does "kill -9" on the process, it doesn't just
disconnect the process from the X server. You'll appreciate this
if you ever did a "kill" on Netscape 4, and watched it keep
eating 100% CPU even though the X server had booted it.
- The workspaces vs. viewports mess was avoided by adding
directional navigation and such to workspaces, see discussion
earlier in this file.
- Instead of configurable placement algorithms, there's just one
that works fairly well most of the time.
- To avoid excess CPU use during opaque move/resize, we rate limit
the updates to the application window's size.
- Instead of configurable "show size of window while resizing,"
it's only shown for windows where it matters, such as terminals.
(Only use-case given for all windows is for web designers
choosing their web browser size, but there are web sites and
desktop backgrounds that do this for you.)
- Using startup notification, applications open on the workspace
where you launched them, not the active workspace when their
window is opened.
- and much more.
Q: I think mutter sucks.
A: Feel free to use any WM you like. The reason metacity follows the
ICCCM and EWMH specifications is that it makes metacity a modular,
interchangeable part in the desktop. libwnck-based apps such as the
GNOME window list will work just fine with any EWMH-compliant WM.
Q: Did you spend a lot of time on this?
A: Originally the answer was no. Sadly the answer is now yes.
Q: How can you claim that you are anti-crack, while still
writing a window manager?
A: I have no comment on that.

View File

@ -5,7 +5,7 @@ srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="mutter"
REQUIRED_AUTOMAKE_VERSION=1.13
REQUIRED_AUTOMAKE_VERSION=1.10
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {

View File

@ -2,8 +2,8 @@ AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [11])
m4_define([mutter_micro_version], [90])
m4_define([mutter_minor_version], [12])
m4_define([mutter_micro_version], [0])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -78,7 +78,7 @@ 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.17.1
$CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1
upower-glib >= 0.99.0
gnome-desktop-3.0
@ -142,11 +142,6 @@ AM_GLIB_GNU_GETTEXT
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"
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
@ -458,7 +453,6 @@ doc/reference/meta-docs.sgml
src/Makefile
src/libmutter-wayland.pc
src/compositor/plugins/Makefile
protocol/Makefile
po/Makefile.in
])

View File

@ -1,4 +1,4 @@
SUBDIRS = man reference
EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \
how-to-get-focus-right.txt
how-to-get-focus-right.txt rationales.txt

View File

@ -16,11 +16,11 @@ src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c
src/core/session.c
src/x11/session.c
src/core/util.c
src/core/window.c
src/core/window-props.c
src/core/xprops.c
src/x11/window-props.c
src/x11/xprops.c
src/mutter-wayland.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/org.gnome.mutter.wayland.gschema.xml.in

View File

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

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 \
@ -28,11 +29,7 @@ INCLUDES= \
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
INCLUDES += \
-I$(srcdir)/wayland \
-I$(builddir)/wayland \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
mutter_built_sources = \
@ -40,16 +37,20 @@ mutter_built_sources = \
$(dbus_xrandr_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
wayland/gtk-shell-protocol.c \
wayland/gtk-shell-server-protocol.h \
wayland/xdg-shell-protocol.c \
wayland/xdg-shell-server-protocol.h \
wayland/xserver-protocol.c \
wayland/xserver-server-protocol.h
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h \
xserver-protocol.c \
xserver-server-protocol.h
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \
wayland/protocol/xserver.xml
libmutter_wayland_la_SOURCES = \
core/async-getprop.c \
core/async-getprop.h \
core/above-tab-keycode.c \
core/barrier.c \
meta/barrier.h \
core/bell.c \
@ -104,7 +105,6 @@ libmutter_wayland_la_SOURCES = \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
meta/compositor-mutter.h \
core/above-tab-keycode.c \
core/constraints.c \
core/constraints.h \
core/core.c \
@ -112,25 +112,18 @@ 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 \
core/edid.h \
core/events.c \
core/events.h \
core/errors.c \
meta/errors.h \
core/frame.c \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/group-private.h \
core/group-props.c \
core/group-props.h \
core/group.c \
meta/group.h \
core/iconcache.c \
core/iconcache.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@ -153,8 +146,6 @@ libmutter_wayland_la_SOURCES = \
core/screen-private.h \
meta/screen.h \
meta/types.h \
core/session.c \
core/session.h \
core/stack.c \
core/stack.h \
core/stack-tracker.c \
@ -162,17 +153,11 @@ libmutter_wayland_la_SOURCES = \
core/util.c \
meta/util.h \
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 \
core/workspace.c \
core/workspace-private.h \
core/xprops.c \
core/xprops.h \
meta/common.h \
core/core.h \
ui/ui.h \
@ -184,14 +169,31 @@ libmutter_wayland_la_SOURCES = \
ui/metaaccellabel.h \
ui/resizepopup.c \
ui/resizepopup.h \
ui/tabpopup.c \
ui/tabpopup.h \
ui/theme-parser.c \
ui/theme.c \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
x11/iconcache.c \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/group-private.h \
x11/group-props.c \
x11/group-props.h \
x11/group.c \
meta/group.h \
x11/session.c \
x11/session.h \
x11/window-props.c \
x11/window-props.h \
x11/window-x11.c \
x11/window-x11.h \
x11/window-x11-private.h \
x11/xprops.c \
x11/xprops.h \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
@ -210,7 +212,9 @@ libmutter_wayland_la_SOURCES = \
wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \
wayland/meta-weston-launch.c \
wayland/meta-weston-launch.h
wayland/meta-weston-launch.h \
wayland/window-wayland.c \
wayland/window-wayland.h
nodist_libmutter_wayland_la_SOURCES = \
$(mutter_built_sources)
@ -311,7 +315,7 @@ endif
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
@ -362,6 +366,7 @@ EXTRA_DIST=$(desktopfiles_files) \
$(desktopfiles_in_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
$(wayland_protocols) \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \
@ -411,9 +416,7 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
--c-generate-object-manager \
$(srcdir)/idle-monitor.xml
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
mkdir -p wayland
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@

View File

@ -19,16 +19,10 @@ struct _MetaCompositor
guint repaint_func_id;
ClutterActor *shadow_src;
MetaPlugin *modal_plugin;
gint64 server_time_query_time;
gint64 server_time_offset;
guint server_time_is_monotonic_time : 1;
guint show_redraw : 1;
guint debug : 1;
guint no_mipmaps : 1;
};
@ -36,10 +30,9 @@ struct _MetaCompScreen
{
MetaScreen *screen;
ClutterActor *stage, *window_group, *top_window_group, *overlay_group;
ClutterActor *stage, *window_group, *top_window_group;
ClutterActor *background_actor;
GList *windows;
GHashTable *windows_by_xid;
Window output;
CoglOnscreen *onscreen;
@ -70,6 +63,4 @@ void meta_end_modal_for_plugin (MetaScreen *screen,
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
gint64 monotonic_time);
void meta_check_end_modal (MetaScreen *screen);
#endif /* META_COMPOSITOR_PRIVATE_H */

View File

@ -65,7 +65,6 @@
#include <meta/window.h>
#include "compositor-private.h"
#include <meta/compositor-mutter.h>
#include "xprops.h"
#include <meta/prefs.h>
#include <meta/main.h>
#include <meta/meta-background-actor.h>
@ -76,14 +75,17 @@
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "util-private.h"
#include "meta-wayland-private.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-keyboard.h"
#include "frame.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
/* #define DEBUG_TRACE g_print */
#define DEBUG_TRACE(X)
#include "wayland/meta-wayland-private.h"
static gboolean
is_modal (MetaDisplay *display)
{
return display->grab_op == META_GRAB_OP_COMPOSITOR;
}
static inline gboolean
composite_at_least_version (MetaDisplay *display, int maj, int min)
@ -108,13 +110,8 @@ meta_finish_workspace_switch (MetaCompScreen *info)
for (l = info->windows; l; l = l->next)
meta_window_actor_sync_visibility (l->data);
/*
* Fix up stacking order in case the plugin messed it up.
*/
/* Fix up stacking order. */
sync_actor_stacking (info);
/* printf ("... FINISHED DESKTOP SWITCH\n"); */
}
void
@ -140,33 +137,12 @@ meta_compositor_destroy (MetaCompositor *compositor)
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
}
static void
add_win (MetaWindow *window)
{
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
g_return_if_fail (info != NULL);
meta_window_actor_new (window);
sync_actor_stacking (info);
}
static void
process_damage (MetaCompositor *compositor,
XDamageNotifyEvent *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;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_process_x11_damage (window_actor, event);
}
@ -371,7 +347,6 @@ begin_modal_x11 (MetaScreen *screen,
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
Cursor cursor = None;
int result;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
@ -391,7 +366,7 @@ begin_modal_x11 (MetaScreen *screen,
META_VIRTUAL_CORE_POINTER_ID,
grab_window,
timestamp,
cursor,
None,
XIGrabModeAsync, XIGrabModeAsync,
False, /* owner_events */
&mask);
@ -435,45 +410,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,
@ -484,19 +420,14 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
* are significant differences in how we handle grabs that make it difficult to
* merge the two.
*/
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompositor *compositor = display->compositor;
gboolean ok;
MetaDisplay *display = meta_screen_get_display (screen);
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
if (meta_is_wayland_compositor ())
ok = begin_modal_wayland (screen, plugin, options, timestamp);
else
ok = begin_modal_x11 (screen, plugin, options, timestamp);
if (!ok)
return FALSE;
if (!meta_is_wayland_compositor ())
if (!begin_modal_x11 (screen, plugin, options, timestamp))
return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL;
@ -504,7 +435,8 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
compositor->modal_plugin = plugin;
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
return TRUE;
}
@ -514,25 +446,10 @@ meta_end_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
guint32 timestamp)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
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
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
}
g_return_if_fail (is_modal (display));
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
@ -540,25 +457,14 @@ meta_end_modal_for_plugin (MetaScreen *screen,
display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE;
compositor->modal_plugin = NULL;
}
/* This is used when reloading plugins to make sure we don't have
* a left-over modal grab for this screen.
*/
void
meta_check_end_modal (MetaScreen *screen)
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompositor *compositor = display->compositor;
if (compositor->modal_plugin &&
meta_plugin_get_screen (compositor->modal_plugin) == screen)
if (meta_is_wayland_compositor ())
{
meta_end_modal_for_plugin (screen,
compositor->modal_plugin,
CurrentTime);
meta_display_sync_wayland_input_focus (display);
}
else
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
}
}
@ -761,18 +667,25 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
}
}
/*
* Shapes the cow so that the given window is exposed,
* when metaWindow is NULL it clears the shape again
/**
* meta_shape_cow_for_window:
* @screen: A #MetaScreen
* @window: (allow-none): A #MetaWindow to shape the COW for
*
* Sets an bounding shape on the COW so that the given window
* is exposed. If @window is %NULL it clears the shape again.
*
* Used so we can unredirect windows, by shaping away the part
* of the COW, letting the raw window be seen through below.
*/
static void
meta_shape_cow_for_window (MetaScreen *screen,
MetaWindow *metaWindow)
MetaWindow *window)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
if (metaWindow == NULL)
if (window == NULL)
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
else
{
@ -781,7 +694,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
int width, height;
MetaRectangle rect;
meta_window_get_frame_rect (metaWindow, &rect);
meta_window_get_frame_rect (window, &rect);
window_bounds.x = rect.x;
window_bounds.y = rect.y;
@ -832,11 +745,12 @@ meta_compositor_add_window (MetaCompositor *compositor,
{
MetaScreen *screen = meta_window_get_screen (window);
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
DEBUG_TRACE ("meta_compositor_add_window\n");
meta_error_trap_push (display);
add_win (window);
meta_window_actor_new (window);
sync_actor_stacking (info);
meta_error_trap_pop (display);
}
@ -845,17 +759,9 @@ void
meta_compositor_remove_window (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = NULL;
MetaScreen *screen;
MetaCompScreen *info;
DEBUG_TRACE ("meta_compositor_remove_window\n");
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info->unredirected_window == window)
set_unredirected_window (info, NULL);
@ -868,13 +774,7 @@ meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen)
{
MetaWindowActor *window_actor;
DEBUG_TRACE ("meta_compositor_set_updates_frozen\n");
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
}
@ -883,13 +783,7 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
MetaWindow *window,
gboolean no_delay_frame)
{
MetaWindowActor *window_actor;
DEBUG_TRACE ("meta_compositor_queue_frame_drawn\n");
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
}
@ -940,6 +834,43 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
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
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
@ -951,6 +882,7 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
*/
static void
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
MetaWindow *window,
XEvent *event)
{
MetaDisplay *display = meta_screen_get_display (info->screen);
@ -959,24 +891,30 @@ maybe_spoof_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);
switch (input_event->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
/* 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 &&
(meta_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:
{
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
/* 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;
@ -996,53 +934,26 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
MetaDisplay *display = compositor->display;
MetaScreen *screen = display->screens->data;
MetaCompScreen *info;
info = meta_screen_get_compositor_data (screen);
if (is_modal (display) && is_grabbed_event (compositor->display, event))
{
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
meta_plugin_manager_xevent_filter (info->plugin_mgr, event);
/* We always consume events even if the plugin says it didn't handle them;
* exclusive is exclusive */
return TRUE;
}
if (window)
{
MetaCompScreen *info;
MetaScreen *screen;
if (!meta_is_wayland_compositor ())
maybe_spoof_event_as_stage_event (info, window, event);
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_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;
}
}
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
return TRUE;
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
@ -1056,7 +967,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
window = meta_display_lookup_x_window (compositor->display, xwin);
}
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
@ -1078,11 +988,7 @@ meta_compositor_filter_keybinding (MetaCompositor *compositor,
MetaKeyBinding *binding)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info->plugin_mgr)
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
return FALSE;
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
}
void
@ -1091,11 +997,7 @@ meta_compositor_show_window (MetaCompositor *compositor,
MetaCompEffect effect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_show_window\n");
if (!window_actor)
return;
meta_window_actor_show (window_actor, effect);
meta_window_actor_show (window_actor, effect);
}
void
@ -1104,10 +1006,6 @@ meta_compositor_hide_window (MetaCompositor *compositor,
MetaCompEffect effect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_hide_window\n");
if (!window_actor)
return;
meta_window_actor_hide (window_actor, effect);
}
@ -1118,10 +1016,6 @@ meta_compositor_maximize_window (MetaCompositor *compositor,
MetaRectangle *new_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_maximize_window\n");
if (!window_actor)
return;
meta_window_actor_maximize (window_actor, old_rect, new_rect);
}
@ -1132,10 +1026,6 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaRectangle *new_rect)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
if (!window_actor)
return;
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
}
@ -1153,18 +1043,14 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
to_indx = meta_workspace_index (to);
from_indx = meta_workspace_index (from);
DEBUG_TRACE ("meta_compositor_switch_workspace\n");
if (!info) /* During startup before manage_screen() */
return;
info->switch_workspace_in_progress++;
if (!info->plugin_mgr ||
!meta_plugin_manager_switch_workspace (info->plugin_mgr,
from_indx,
to_indx,
direction))
if (!meta_plugin_manager_switch_workspace (info->plugin_mgr,
from_indx, to_indx,
direction))
{
info->switch_workspace_in_progress--;
@ -1273,8 +1159,6 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
GList *old_stack;
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
DEBUG_TRACE ("meta_compositor_sync_stack\n");
/* This is painful because hidden windows that we are in the process
* of animating out of existence. They'll be at the bottom of the
* stack of X windows, but we want to leave them in their old position
@ -1363,15 +1247,6 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
gboolean did_placement)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
g_return_if_fail (info);
if (!window_actor)
return;
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
}
@ -1403,7 +1278,6 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
Display *xdisplay;
Window xwin;
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
g_return_if_fail (info);
xdisplay = meta_display_get_xdisplay (display);
@ -1707,10 +1581,6 @@ meta_compositor_show_tile_preview (MetaCompositor *compositor,
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);
}
@ -1720,9 +1590,5 @@ 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);
}

View File

@ -100,7 +100,9 @@ meta_plugin_manager_new (MetaScreen *screen)
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL);
_meta_plugin_set_screen (plugin, screen);
klass = META_PLUGIN_GET_CLASS (plugin);
@ -165,8 +167,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin);
klass->minimize (plugin, actor);
}
break;
@ -176,8 +176,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin);
klass->map (plugin, actor);
}
break;
@ -185,7 +183,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
if (klass->destroy)
{
retval = TRUE;
_meta_plugin_effect_started (plugin);
klass->destroy (plugin, actor);
}
break;
@ -230,8 +227,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin);
klass->maximize (plugin, actor,
target_x, target_y,
target_width, target_height);
@ -243,8 +238,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
_meta_plugin_effect_started (plugin);
klass->unmaximize (plugin, actor,
target_x, target_y,
target_width, target_height);
@ -283,8 +276,6 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
{
retval = TRUE;
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
_meta_plugin_effect_started (plugin);
klass->switch_workspace (plugin, from, to, direction);
}

View File

@ -30,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>
@ -46,91 +47,15 @@ G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
#define META_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
enum
{
PROP_0,
PROP_SCREEN,
PROP_DEBUG_MODE,
};
struct _MetaPluginPrivate
{
MetaScreen *screen;
gint running;
gboolean debug : 1;
MetaScreen *screen;
};
static void
meta_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
priv->screen = g_value_get_object (value);
break;
case PROP_DEBUG_MODE:
priv->debug = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
g_value_set_object (value, priv->screen);
break;
case PROP_DEBUG_MODE:
g_value_set_boolean (value, priv->debug);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_plugin_class_init (MetaPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = meta_plugin_set_property;
gobject_class->get_property = meta_plugin_get_property;
g_object_class_install_property (gobject_class,
PROP_SCREEN,
g_param_spec_object ("screen",
"MetaScreen",
"MetaScreen",
META_TYPE_SCREEN,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DEBUG_MODE,
g_param_spec_boolean ("debug-mode",
"Debug Mode",
"Debug Mode",
FALSE,
G_PARAM_READABLE));
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
g_type_class_add_private (klass, sizeof (MetaPluginPrivate));
}
static void
@ -139,22 +64,6 @@ meta_plugin_init (MetaPlugin *self)
self->priv = META_PLUGIN_GET_PRIVATE (self);
}
gboolean
meta_plugin_running (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return (priv->running > 0);
}
gboolean
meta_plugin_debug_mode (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->debug;
}
const MetaPluginInfo *
meta_plugin_get_info (MetaPlugin *plugin)
{
@ -166,21 +75,6 @@ meta_plugin_get_info (MetaPlugin *plugin)
return NULL;
}
/**
* _meta_plugin_effect_started:
* @plugin: the plugin
*
* Mark that an effect has started for the plugin. This is called
* internally by MetaPluginManager.
*/
void
_meta_plugin_effect_started (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
priv->running++;
}
gboolean
_meta_plugin_xevent_filter (MetaPlugin *plugin,
XEvent *xev)
@ -207,15 +101,8 @@ void
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
if (priv->running-- < 0)
{
g_warning ("Error in running effect accounting, adjusting.");
priv->running = 0;
}
meta_switch_workspace_completed (screen);
}
@ -224,26 +111,6 @@ meta_plugin_window_effect_completed (MetaPlugin *plugin,
MetaWindowActor *actor,
unsigned long event)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
if (priv->running-- < 0)
{
g_warning ("Error in running effect accounting, adjusting.");
priv->running = 0;
}
if (!actor)
{
const MetaPluginInfo *info;
const gchar *name = NULL;
if (plugin && (info = meta_plugin_get_info (plugin)))
name = info->name;
g_warning ("Plugin [%s] passed NULL for actor!",
name ? name : "unknown");
}
meta_window_actor_effect_completed (actor, event);
}
@ -338,9 +205,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
* meta_plugin_get_screen:
* @plugin: a #MetaPlugin
*
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
* is associated with exactly one screen; if Metacity is managing
* multiple screens, multiple plugin instances will be created.
* Gets the #MetaScreen corresponding to a plugin.
*
* Return value: (transfer none): the #MetaScreen for the plugin
*/
@ -352,6 +217,15 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen;
}
void
_meta_plugin_set_screen (MetaPlugin *plugin,
MetaScreen *screen)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
priv->screen = screen;
}
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok)

View File

@ -33,6 +33,7 @@
#include "meta-texture-tower.h"
#include "meta-shaped-texture-private.h"
#include "meta-window-actor-private.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
@ -576,8 +577,18 @@ static cairo_region_t *
effective_unobscured_region (MetaShapedTexture *self)
{
MetaShapedTexturePrivate *priv = self->priv;
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
return NULL;
while (parent && !META_IS_WINDOW_ACTOR (parent))
parent = clutter_actor_get_parent (parent);
if (parent && clutter_actor_has_mapped_clones (parent))
return NULL;
return priv->unobscured_region;
}
gboolean

View File

@ -29,15 +29,30 @@
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
#include "wayland/meta-wayland-private.h"
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
MetaWaylandBuffer *buffer;
struct wl_listener buffer_destroy_listener;
};
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
static void
meta_surface_actor_handle_buffer_destroy (struct wl_listener *listener, void *data)
{
MetaSurfaceActorWaylandPrivate *priv = wl_container_of (listener, priv, buffer_destroy_listener);
/* If the buffer is destroyed while we're attached to it,
* we want to unset priv->buffer so we don't access freed
* memory. Keep the texture set however so the user doesn't
* see the window disappear. */
priv->buffer = NULL;
}
static void
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
@ -45,16 +60,19 @@ meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
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)
if (priv->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);
}
struct wl_resource *resource = priv->buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
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
@ -65,8 +83,21 @@ 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;
MetaShapedTexture *stex = meta_surface_actor_get_texture (actor);
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
switch (cogl_texture_get_components (texture))
{
case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE;
case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH:
return FALSE;
default:
g_assert_not_reached ();
}
}
static gboolean
@ -97,6 +128,14 @@ 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)
{
@ -110,11 +149,16 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
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)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy;
}
MetaSurfaceActor *
@ -137,10 +181,16 @@ meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
if (priv->buffer)
wl_list_remove (&priv->buffer_destroy_listener.link);
priv->buffer = buffer;
if (buffer)
meta_shaped_texture_set_texture (stex, buffer->texture);
if (priv->buffer)
{
wl_signal_add (&priv->buffer->destroy_signal, &priv->buffer_destroy_listener);
meta_shaped_texture_set_texture (stex, priv->buffer->texture);
}
else
meta_shaped_texture_set_texture (stex, NULL);
}

View File

@ -29,7 +29,7 @@
#include "meta-surface-actor.h"
#include "meta-wayland-private.h"
#include "wayland/meta-wayland.h"
G_BEGIN_DECLS

View File

@ -387,6 +387,14 @@ meta_surface_actor_x11_dispose (GObject *object)
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)
{
@ -403,6 +411,8 @@ meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
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
@ -456,6 +466,7 @@ meta_surface_actor_x11_new (MetaWindow *window)
priv->unredirected = FALSE;
sync_unredirected (self);
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
return META_SURFACE_ACTOR (self);
}

View File

@ -15,7 +15,6 @@
#include <clutter/clutter.h>
#include <meta/meta-shaped-texture.h>
#include "meta-wayland-private.h"
#include "meta-cullable.h"
#include "meta-shaped-texture-private.h"
@ -26,8 +25,8 @@ struct _MetaSurfaceActorPrivate
cairo_region_t *input_region;
/* Freeze/thaw accounting */
guint freeze_count;
guint needs_damage_all : 1;
guint frozen : 1;
};
static void cullable_iface_init (MetaCullableInterface *iface);
@ -223,7 +222,7 @@ static gboolean
is_frozen (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv = self->priv;
return (priv->freeze_count > 0);
return priv->frozen;
}
void
@ -274,31 +273,19 @@ meta_surface_actor_is_visible (MetaSurfaceActor *self)
}
void
meta_surface_actor_freeze (MetaSurfaceActor *self)
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
gboolean frozen)
{
MetaSurfaceActorPrivate *priv = self->priv;
priv->freeze_count ++;
}
priv->frozen = frozen;
void
meta_surface_actor_thaw (MetaSurfaceActor *self)
{
MetaSurfaceActorPrivate *priv = self->priv;
if (priv->freeze_count == 0)
if (!frozen && priv->needs_damage_all)
{
g_critical ("Error in freeze/thaw accounting.");
return;
}
/* 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. */
priv->freeze_count --;
/* 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. */
if (priv->needs_damage_all)
{
meta_surface_actor_process_damage (self, 0, 0,
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
@ -306,12 +293,6 @@ meta_surface_actor_thaw (MetaSurfaceActor *self)
}
}
gboolean
meta_surface_actor_is_frozen (MetaSurfaceActor *self)
{
return is_frozen (self);
}
gboolean
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
{
@ -330,3 +311,9 @@ 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

@ -6,6 +6,7 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include <meta/window.h>
G_BEGIN_DECLS
@ -35,6 +36,8 @@ struct _MetaSurfaceActorClass
void (* set_unredirected) (MetaSurfaceActor *actor,
gboolean unredirected);
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
};
struct _MetaSurfaceActor
@ -50,6 +53,7 @@ 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,
@ -69,9 +73,8 @@ 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_freeze (MetaSurfaceActor *actor);
void meta_surface_actor_thaw (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_frozen (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,

View File

@ -5,9 +5,6 @@
#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"
@ -63,5 +60,6 @@ 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 */

View File

@ -20,7 +20,6 @@
#include "frame.h"
#include <meta/window.h>
#include <meta/meta-shaped-texture.h>
#include "xprops.h"
#include "compositor-private.h"
#include "meta-shaped-texture-private.h"
@ -28,13 +27,14 @@
#include "meta-window-actor-private.h"
#include "meta-texture-rectangle.h"
#include "region-utils.h"
#include "meta-wayland-private.h"
#include "monitor-private.h"
#include "meta-cullable.h"
#include "meta-surface-actor.h"
#include "meta-surface-actor-x11.h"
#include "wayland/meta-wayland-surface.h"
struct _MetaWindowActorPrivate
{
MetaWindow *window;
@ -84,6 +84,7 @@ struct _MetaWindowActorPrivate
/* List of FrameData for recent frames */
GList *frames;
guint freeze_count;
guint visible : 1;
guint disposed : 1;
@ -253,7 +254,15 @@ static gboolean
is_argb32 (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_is_argb32 (priv->surface);
/* assume we're argb until we get the window (because
in practice we're drawing nothing, so we're fully
transparent)
*/
if (priv->surface)
return meta_surface_actor_is_argb32 (priv->surface);
else
return TRUE;
}
static gboolean
@ -269,14 +278,19 @@ static gboolean
is_frozen (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_is_frozen (priv->surface);
return priv->surface == NULL || priv->freeze_count > 0;
}
static void
meta_window_actor_freeze (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
meta_surface_actor_freeze (priv->surface);
if (priv->freeze_count == 0 && priv->surface)
meta_surface_actor_set_frozen (priv->surface, TRUE);
priv->freeze_count ++;
}
static void
@ -284,11 +298,16 @@ meta_window_actor_thaw (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
meta_surface_actor_thaw (priv->surface);
if (priv->freeze_count <= 0)
g_error ("Error in freeze/thaw accounting");
if (is_frozen (self))
priv->freeze_count--;
if (priv->freeze_count > 0)
return;
if (priv->surface)
meta_surface_actor_set_frozen (priv->surface, FALSE);
/* We sometimes ignore moves and resizes on frozen windows */
meta_window_actor_sync_actor_geometry (self, FALSE);
@ -326,14 +345,13 @@ set_surface (MetaWindowActor *self,
/* If the previous surface actor was frozen, start out
* frozen as well... */
if (priv->updates_frozen)
meta_surface_actor_freeze (priv->surface);
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
meta_window_actor_update_shape (self);
}
}
static void
void
meta_window_actor_update_surface (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
@ -342,8 +360,10 @@ meta_window_actor_update_surface (MetaWindowActor *self)
if (window->surface)
surface_actor = window->surface->surface_actor;
else
else if (!meta_is_wayland_compositor ())
surface_actor = meta_surface_actor_x11_new (window);
else
surface_actor = NULL;
set_surface (self, surface_actor);
}
@ -650,8 +670,11 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
meta_window_actor_get_shape_bounds (self, &bounds);
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
if (priv->surface)
{
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
}
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
{
@ -691,7 +714,7 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
/* Leaving out shadows for maximized and fullscreen windows is an effeciency
* win and also prevents the unsightly effect of the shadow of maximized
* window appearing on an adjacent window */
if ((meta_window_get_maximized (priv->window) == (META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL)) ||
if ((meta_window_get_maximized (priv->window) == META_MAXIMIZE_BOTH) ||
meta_window_is_fullscreen (priv->window))
return FALSE;
@ -762,21 +785,26 @@ meta_window_actor_get_meta_window (MetaWindowActor *self)
* meta_window_actor_get_texture:
* @self: a #MetaWindowActor
*
* Gets the ClutterActor that is used to display the contents of the window
* Gets the ClutterActor that is used to display the contents of the window,
* or NULL if no texture is shown yet, because the window is not mapped.
*
* Return value: (transfer none): the #ClutterActor for the contents
*/
ClutterActor *
meta_window_actor_get_texture (MetaWindowActor *self)
{
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
if (self->priv->surface)
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
else
return NULL;
}
/**
* meta_window_actor_get_surface:
* @self: a #MetaWindowActor
*
* Gets the MetaSurfaceActor that draws the content of this window
* Gets the MetaSurfaceActor that draws the content of this window,
* or NULL if there is no surface yet associated with this window.
*
* Return value: (transfer none): the #MetaSurfaceActor for the contents
*/
@ -875,7 +903,12 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
if (!priv->repaint_scheduled)
{
gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface);
gboolean is_obscured;
if (priv->surface)
is_obscured = meta_surface_actor_is_obscured (priv->surface);
else
is_obscured = FALSE;
/* A frame was marked by the client without actually doing any
* damage or any unobscured, or while we had the window frozen
@ -891,9 +924,12 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
}
else
{
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
priv->repaint_scheduled = TRUE;
if (priv->surface)
{
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
priv->repaint_scheduled = TRUE;
}
}
}
}
@ -932,9 +968,6 @@ start_simple_effect (MetaWindowActor *self,
gint *counter = NULL;
gboolean use_freeze_thaw = FALSE;
if (!info->plugin_mgr)
return FALSE;
switch (event)
{
case META_PLUGIN_MINIMIZE:
@ -1066,7 +1099,10 @@ gboolean
meta_window_actor_should_unredirect (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_should_unredirect (priv->surface);
if (priv->surface)
return meta_surface_actor_should_unredirect (priv->surface);
else
return FALSE;
}
void
@ -1074,6 +1110,8 @@ meta_window_actor_set_unredirected (MetaWindowActor *self,
gboolean unredirected)
{
MetaWindowActorPrivate *priv = self->priv;
g_assert(priv->surface); /* because otherwise should_unredirect() is FALSE */
meta_surface_actor_set_unredirected (priv->surface, unredirected);
}
@ -1258,8 +1296,7 @@ meta_window_actor_maximize (MetaWindowActor *self,
self->priv->maximize_in_progress++;
meta_window_actor_freeze (self);
if (!info->plugin_mgr ||
!meta_plugin_manager_event_maximize (info->plugin_mgr,
if (!meta_plugin_manager_event_maximize (info->plugin_mgr,
self,
META_PLUGIN_MAXIMIZE,
new_rect->x, new_rect->y,
@ -1287,8 +1324,7 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
self->priv->unmaximize_in_progress++;
meta_window_actor_freeze (self);
if (!info->plugin_mgr ||
!meta_plugin_manager_event_maximize (info->plugin_mgr,
if (!meta_plugin_manager_event_maximize (info->plugin_mgr,
self,
META_PLUGIN_UNMAXIMIZE,
new_rect->x, new_rect->y,
@ -1430,6 +1466,7 @@ meta_window_actor_cull_out (MetaCullable *cullable,
{
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
meta_window_actor_set_clip_region_beneath (self, clip_region);
}
@ -1519,11 +1556,12 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
{
MetaWindowActorPrivate *priv = self->priv;
meta_surface_actor_process_damage (priv->surface,
event->area.x,
event->area.y,
event->area.width,
event->area.height);
if (priv->surface)
meta_surface_actor_process_damage (priv->surface,
event->area.x,
event->area.y,
event->area.width,
event->area.height);
}
void
@ -1671,22 +1709,25 @@ build_and_scan_frame_mask (MetaWindowActor *self,
}
meta_shaped_texture_set_mask_texture (stex, mask_texture);
cogl_object_unref (mask_texture);
if (mask_texture)
cogl_object_unref (mask_texture);
g_free (mask_data);
}
static void
meta_window_actor_update_shape_region (MetaWindowActor *self,
cairo_rectangle_int_t *client_area)
meta_window_actor_update_shape_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *region = NULL;
cairo_rectangle_int_t client_area;
meta_window_get_client_area_rect (priv->window, &client_area);
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
{
region = cairo_region_copy (priv->window->shape_region);
cairo_region_translate (region, client_area->x, client_area->y);
cairo_region_translate (region, client_area.x, client_area.y);
}
else if (priv->window->shape_region != NULL)
{
@ -1697,11 +1738,11 @@ meta_window_actor_update_shape_region (MetaWindowActor *self,
/* If we don't have a shape on the server, that means that
* we have an implicit shape of one rectangle covering the
* entire window. */
region = cairo_region_create_rectangle (client_area);
region = cairo_region_create_rectangle (&client_area);
}
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
build_and_scan_frame_mask (self, client_area, region);
build_and_scan_frame_mask (self, &client_area, region);
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
priv->shape_region = region;
@ -1712,34 +1753,43 @@ meta_window_actor_update_shape_region (MetaWindowActor *self,
}
static void
meta_window_actor_update_input_region (MetaWindowActor *self,
cairo_rectangle_int_t *client_area)
meta_window_actor_update_input_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *region = NULL;
cairo_rectangle_int_t client_area;
if (priv->window->frame != NULL && priv->window->input_region != NULL)
meta_window_get_client_area_rect (priv->window, &client_area);
if (priv->window->frame != NULL)
{
region = meta_frame_get_frame_bounds (priv->window->frame);
cairo_region_subtract_rectangle (region, client_area);
/* input_region is in client window coordinates, so translate the
* input region into that coordinate system and back */
cairo_region_translate (region, -client_area->x, -client_area->y);
cairo_region_union (region, priv->window->input_region);
cairo_region_translate (region, client_area->x, client_area->y);
cairo_region_translate (region, -client_area.x, -client_area.y);
cairo_region_union_rectangle (region, &client_area);
cairo_region_translate (region, client_area.x, client_area.y);
}
else if (priv->window->input_region != NULL)
else if (priv->window->shape_region != NULL ||
priv->window->input_region != NULL)
{
region = cairo_region_reference (priv->window->input_region);
if (priv->window->shape_region != NULL)
{
region = cairo_region_copy (priv->window->shape_region);
if (priv->window->input_region != NULL)
cairo_region_intersect (region, priv->window->input_region);
}
else
region = cairo_region_reference (priv->window->input_region);
}
else
{
/* If we don't have a shape on the server, that means that
* we have an implicit shape of one rectangle covering the
* entire window. */
region = cairo_region_create_rectangle (client_area);
region = cairo_region_create_rectangle (&client_area);
}
meta_surface_actor_set_input_region (priv->surface, region);
@ -1755,9 +1805,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
if (argb32 && priv->window->opaque_region != NULL)
{
MetaFrameBorders borders;
cairo_rectangle_int_t client_area;
meta_frame_calc_borders (priv->window->frame, &borders);
meta_window_get_client_area_rect (priv->window, &client_area);
/* The opaque region is defined to be a part of the
* window which ARGB32 will always paint with opaque
@ -1770,7 +1820,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
* case, graphical glitches will occur.
*/
opaque_region = cairo_region_copy (priv->window->opaque_region);
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
cairo_region_translate (opaque_region, client_area.x, client_area.y);
cairo_region_intersect (opaque_region, priv->shape_region);
}
else if (argb32)
@ -1786,27 +1836,15 @@ static void
check_needs_reshape (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaFrameBorders borders;
cairo_rectangle_int_t client_area;
if (!priv->needs_reshape)
return;
meta_frame_calc_borders (priv->window->frame, &borders);
client_area.x = borders.total.left;
client_area.y = borders.total.top;
client_area.width = priv->window->rect.width;
if (priv->window->shaded)
client_area.height = 0;
else
client_area.height = priv->window->rect.height;
meta_window_actor_update_shape_region (self, &client_area);
meta_window_actor_update_shape_region (self);
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
meta_window_actor_update_input_region (self, &client_area);
meta_window_actor_update_input_region (self);
meta_window_actor_update_opaque_region (self);
}
@ -2026,7 +2064,8 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
clutter_actor_set_opacity (CLUTTER_ACTOR (self->priv->surface), window->opacity);
if (priv->surface)
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
}
void

View File

@ -58,88 +58,6 @@
#include <canberra-gtk.h>
#endif
/**
* bell_flash_screen:
* @display: The display which owns the screen (rather redundant)
* @screen: The screen to flash
*
* Flashes one entire screen. This is done by making a window the size of the
* whole screen (or reusing the old one, if it's still around), mapping it,
* painting it white and then black, and then unmapping it. We set saveunder so
* that all the windows behind it come back immediately.
*
* Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather,
* we do them in one go, because we don't have to rely on the theme code
* redrawing the frame for us in order to do the flash.
*/
/*
* Bug: The way I read it, this appears not to do the flash
* the first time we flash a particular display. Am I wrong?
*
* Bug: This appears to destroy our current XSync status.
*/
static void
bell_flash_screen (MetaDisplay *display,
MetaScreen *screen)
{
Window root = screen->xroot;
int width = screen->rect.width;
int height = screen->rect.height;
if (screen->flash_window == None)
{
Visual *visual = (Visual *)CopyFromParent;
XSetWindowAttributes xswa;
int depth = CopyFromParent;
xswa.save_under = True;
xswa.override_redirect = True;
/*
* TODO: use XGetVisualInfo and determine which is an
* overlay, if one is present, and use the Overlay visual
* for this window (for performance reasons).
* Not sure how to tell this yet...
*/
screen->flash_window = XCreateWindow (display->xdisplay, root,
0, 0, width, height,
0, depth,
InputOutput,
visual,
/* note: XSun doesn't like SaveUnder here */
CWSaveUnder | CWOverrideRedirect,
&xswa);
XSelectInput (display->xdisplay, screen->flash_window, ExposureMask);
XMapWindow (display->xdisplay, screen->flash_window);
XSync (display->xdisplay, False);
XFlush (display->xdisplay);
XUnmapWindow (display->xdisplay, screen->flash_window);
}
else
{
/* just draw something in the window */
GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL);
XMapWindow (display->xdisplay, screen->flash_window);
XSetForeground (display->xdisplay, gc,
WhitePixel (display->xdisplay,
XScreenNumberOfScreen (screen->xscreen)));
XFillRectangle (display->xdisplay, screen->flash_window, gc,
0, 0, width, height);
XSetForeground (display->xdisplay, gc,
BlackPixel (display->xdisplay,
XScreenNumberOfScreen (screen->xscreen)));
XFillRectangle (display->xdisplay, screen->flash_window, gc,
0, 0, width, height);
XFlush (display->xdisplay);
XSync (display->xdisplay, False);
XUnmapWindow (display->xdisplay, screen->flash_window);
XFreeGC (display->xdisplay, gc);
}
if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK &&
!display->mouse_mode)
meta_display_increment_focus_sentinel (display);
XFlush (display->xdisplay);
}
/**
* bell_flash_fullscreen:
* @display: The display the event came in on
@ -164,12 +82,7 @@ bell_flash_fullscreen (MetaDisplay *display,
{
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
if (screen)
{
if (display->compositor)
meta_compositor_flash_screen (display->compositor, screen);
else
bell_flash_screen (display, screen);
}
meta_compositor_flash_screen (display->compositor, screen);
}
else
{
@ -177,10 +90,7 @@ bell_flash_fullscreen (MetaDisplay *display,
while (screen_list)
{
screen = (MetaScreen *) screen_list->data;
if (display->compositor)
meta_compositor_flash_screen (display->compositor, screen);
else
bell_flash_screen (display, screen);
meta_compositor_flash_screen (display->compositor, screen);
screen_list = screen_list->next;
}
}

View File

@ -425,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)
@ -491,12 +492,17 @@ place_window_if_needed(MetaWindow *window,
!window->minimized &&
!window->fullscreen)
{
MetaRectangle orig_rect;
MetaRectangle placed_rect;
MetaWorkspace *cur_workspace;
const MetaMonitorInfo *monitor_info;
meta_window_get_frame_rect (window, &placed_rect);
meta_window_place (window, info->orig.x, info->orig.y,
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;

View File

@ -27,16 +27,6 @@
#include "window-private.h"
#include "frame.h"
typedef enum
{
META_IS_CONFIGURE_REQUEST = 1 << 0,
META_DO_GRAVITY_ADJUST = 1 << 1,
META_IS_USER_ACTION = 1 << 2,
META_IS_MOVE_ACTION = 1 << 3,
META_IS_RESIZE_ACTION = 1 << 4,
META_IS_WAYLAND_RESIZE = 1 << 5
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,
MetaMoveResizeFlags flags,
int resize_gravity,

View File

@ -328,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
@ -342,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
@ -359,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
@ -376,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
@ -392,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
@ -726,16 +718,6 @@ meta_core_set_screen_cursor (Display *xdisplay,
meta_frame_set_screen_cursor (window->frame, cursor);
}
void
meta_core_increment_event_serial (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
meta_display_increment_event_serial (display);
}
void
meta_invalidate_default_icons (void)
{

View File

@ -193,12 +193,6 @@ void meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
MetaCursor cursor);
/* Used because we ignore EnterNotify when a window is unmapped that
* really shouldn't cause focus changes, by comparing the event serial
* of the EnterNotify and the UnmapNotify.
*/
void meta_core_increment_event_serial (Display *display);
void meta_invalidate_default_icons (void);
void meta_core_add_old_event_mask (Display *xdisplay,

View File

@ -37,7 +37,7 @@
#include <stdlib.h>
#include <stdio.h>
#include "meta-wayland-surface.h"
#include "wayland/meta-wayland-surface.h"
static void meta_window_present_delete_dialog (MetaWindow *window,
guint32 timestamp);
@ -143,31 +143,7 @@ void
meta_window_delete (MetaWindow *window,
guint32 timestamp)
{
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
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_wayland_surface_delete (window->surface);
}
META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
meta_window_check_alive (window, timestamp);
@ -200,33 +176,10 @@ meta_window_delete (MetaWindow *window,
}
}
void
meta_window_kill (MetaWindow *window)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Killing %s brutally\n",
window->desc);
if (!meta_window_is_remote (window) &&
window->net_wm_pid > 0)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Killing %s with kill()\n",
window->desc);
if (kill (window->net_wm_pid, 9) < 0)
meta_topic (META_DEBUG_WINDOW_OPS,
"Failed to signal %s: %s\n",
window->desc, strerror (errno));
}
meta_topic (META_DEBUG_WINDOW_OPS,
"Disconnecting %s with XKillClient()\n",
window->desc);
meta_error_trap_push (window->display);
XKillClient (window->display->xdisplay, window->xwindow);
meta_error_trap_pop (window->display);
META_WINDOW_GET_CLASS (window)->kill (window);
}
void
@ -261,8 +214,7 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
{
MetaWindow *w = tmp->data;
if (w->xtransient_for == window->xwindow &&
w->res_class &&
if (w->transient_for == window && w->res_class &&
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
{
meta_window_activate (w, timestamp);

View File

@ -145,8 +145,6 @@ struct _MetaDisplay
* multiple events with the same serial.
*/
guint focused_by_us : 1;
guint static_gravity_works : 1;
/*< private-ish >*/
guint error_trap_synced_at_last_pop : 1;
@ -215,7 +213,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;
@ -233,8 +230,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;
@ -457,6 +454,9 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
gboolean meta_grab_op_is_moving (MetaGrabOp op);
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
gboolean meta_grab_op_is_wayland (MetaGrabOp op);
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
void meta_display_devirtualize_modifiers (MetaDisplay *display,
MetaVirtualModifier modifiers,
@ -489,4 +489,16 @@ void meta_display_set_input_focus_xwindow (MetaDisplay *display,
Window window,
guint32 timestamp);
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
void meta_display_update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial,
gboolean focused_by_us);
void meta_display_sanity_check_timestamps (MetaDisplay *display,
guint32 timestamp);
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
guint32 *timestamp);
#endif

File diff suppressed because it is too large Load Diff

2263
src/core/events.c Normal file

File diff suppressed because it is too large Load Diff

32
src/core/events.h Normal file
View File

@ -0,0 +1,32 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
* Copyright (C) 2003, 2004 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <meta/display.h>
#ifndef META_EVENTS_H
#define META_EVENTS_H
void meta_display_init_events (MetaDisplay *display);
void meta_display_free_events (MetaDisplay *display);
#endif

View File

@ -35,8 +35,7 @@
ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | PointerMotionHintMask | \
EnterWindowMask | LeaveWindowMask | \
FocusChangeMask | \
ColormapChangeMask)
FocusChangeMask)
void
meta_window_ensure_frame (MetaWindow *window)

View File

@ -30,6 +30,7 @@
#include <gio/gio.h>
#include <meta/keybindings.h>
typedef struct _MetaKeyHandler MetaKeyHandler;
struct _MetaKeyHandler
{
char *name;
@ -47,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);
@ -77,5 +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

@ -42,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>
@ -50,10 +50,8 @@
#include "display-private.h"
#include <meta/errors.h>
#include "ui.h"
#include "session.h"
#include <meta/prefs.h>
#include <meta/compositor.h>
#include "meta-wayland-private.h"
#include <glib-object.h>
#include <glib-unix.h>
@ -79,6 +77,10 @@
#include <girepository.h>
#endif
#include "x11/session.h"
#include "wayland/meta-wayland.h"
/*
* The exit code we'll return to our parent process when we eventually die.
*/
@ -190,6 +192,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[] = {
{
@ -233,6 +236,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}
};
@ -401,8 +409,7 @@ meta_init (void)
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
/* We consider running from mutter-launch equivalent to running from bare metal. */
if (getenv ("WESTON_LAUNCHER_SOCK"))
if (opt_display_server)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
meta_set_is_wayland_compositor (opt_wayland);
@ -497,6 +504,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

@ -43,4 +43,7 @@ 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_force_update (MetaCursorTracker *tracker);
#endif

View File

@ -39,6 +39,7 @@
#include <gbm.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
@ -46,9 +47,10 @@
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "meta-wayland-private.h"
#include "monitor-private.h"
#include "wayland/meta-wayland-private.h"
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
@ -569,6 +571,9 @@ 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));
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
@ -1074,12 +1079,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
@ -1095,9 +1101,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
@ -1139,3 +1148,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

@ -650,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

@ -34,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"

View File

@ -344,7 +344,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *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? */
window->type == META_WINDOW_MODAL_DIALOG &&
meta_window_same_application (window, focus_window) &&
window_overlaps_focus_window (window))
{
@ -610,7 +610,7 @@ meta_window_place (MetaWindow *window,
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
windows = NULL;
switch (window->type)
{
/* Run placement algorithm on these. */
@ -638,7 +638,7 @@ meta_window_place (MetaWindow *window,
case META_WINDOW_OVERRIDE_OTHER:
goto done_no_constraints;
}
if (meta_prefs_get_disable_workarounds ())
{
switch (window->type)
@ -699,18 +699,11 @@ meta_window_place (MetaWindow *window,
goto done_no_constraints;
}
}
if ((window->type == META_WINDOW_DIALOG ||
window->type == META_WINDOW_MODAL_DIALOG) &&
window->xtransient_for != None)
{
/* Center horizontally, at top of parent vertically */
MetaWindow *parent;
parent =
meta_display_lookup_x_window (window->display,
window->xtransient_for);
if (window->type == META_WINDOW_DIALOG ||
window->type == META_WINDOW_MODAL_DIALOG)
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (parent)
{

View File

@ -57,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 */
@ -112,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,
@ -365,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,
@ -1813,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";
@ -1869,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);
@ -1879,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;
@ -1891,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++)
{
@ -1933,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))
@ -1968,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;
}
@ -2103,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;
@ -2167,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 ()
{
@ -2272,7 +2254,7 @@ meta_prefs_get_window_binding (const char *name,
if (pref->per_window)
{
GSList *s = pref->bindings;
GSList *s = pref->combos;
while (s)
{
@ -2320,25 +2302,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

@ -64,7 +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;
guint tile_preview_timeout_id;
@ -83,8 +82,6 @@ struct _MetaScreen
MetaCursorTracker *cursor_tracker;
MetaCursor current_cursor;
Window flash_window;
Window wm_sn_selection_window;
Atom wm_sn_atom;
guint32 wm_sn_timestamp;
@ -150,22 +147,6 @@ 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_update_tile_preview (MetaScreen *screen,
gboolean delay);
void meta_screen_hide_tile_preview (MetaScreen *screen);

View File

@ -39,11 +39,9 @@
#include "workspace-private.h"
#include "keybindings-private.h"
#include "stack.h"
#include "xprops.h"
#include <meta/compositor.h>
#include "mutter-enum-types.h"
#include "core.h"
#include "meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
@ -54,6 +52,8 @@
#include <stdio.h>
#include <stdlib.h>
#include "x11/xprops.h"
static char* get_screen_name (MetaDisplay *display,
int number);
@ -308,6 +308,8 @@ set_supported_hint (MetaScreen *screen)
#include <meta/atomnames.h>
#undef item
#undef EWMH_ATOMS_ONLY
screen->display->atom__GTK_FRAME_EXTENTS,
};
XChangeProperty (screen->display->xdisplay, screen->xroot,
@ -688,7 +690,6 @@ meta_screen_new (MetaDisplay *display,
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
screen->flash_window = None;
screen->wm_sn_selection_window = new_wm_sn_owner;
screen->wm_sn_atom = wm_sn_atom;
@ -760,9 +761,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_timeout_id = 0;
screen->stack = meta_stack_new (screen);
@ -810,11 +808,8 @@ meta_screen_free (MetaScreen *screen,
meta_display_grab (display);
if (screen->display->compositor)
{
meta_compositor_unmanage_screen (screen->display->compositor,
screen);
}
meta_compositor_unmanage_screen (screen->display->compositor,
screen);
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
@ -1428,253 +1423,6 @@ 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_frame_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_update_tile_preview_timeout (gpointer data)
{
@ -1762,38 +1510,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;
}
@ -2075,28 +1804,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;
@ -2807,10 +2519,9 @@ on_monitors_changed (MetaMonitorManager *manager,
&changes);
}
if (screen->display->compositor)
meta_compositor_sync_screen_size (screen->display->compositor,
screen,
screen->rect.width, screen->rect.height);
meta_compositor_sync_screen_size (screen->display->compositor,
screen,
screen->rect.width, screen->rect.height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);

View File

@ -1245,10 +1245,9 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window);
}
if (tracker->screen->display->compositor)
meta_compositor_sync_stack (tracker->screen->display->compositor,
tracker->screen,
meta_windows);
meta_compositor_sync_stack (tracker->screen->display->compositor,
tracker->screen,
meta_windows);
g_list_free (meta_windows);
meta_screen_restacked (tracker->screen);

View File

@ -36,6 +36,8 @@
#include <X11/Xatom.h>
#include "x11/group-private.h"
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
(w->type == META_WINDOW_DIALOG || \
w->type == META_WINDOW_MODAL_DIALOG || \
@ -1705,8 +1707,8 @@ get_default_focus_window (MetaStack *stack,
MetaWindow *topmost_in_group;
MetaWindow *topmost_overall;
MetaGroup *not_this_one_group;
GList *link;
GList *l;
transient_parent = NULL;
topmost_in_group = NULL;
topmost_overall = NULL;
@ -1718,49 +1720,49 @@ get_default_focus_window (MetaStack *stack,
stack_ensure_sorted (stack);
/* top of this layer is at the front of the list */
link = stack->sorted;
while (link)
for (l = stack->sorted; l != NULL; l = l->next)
{
MetaWindow *window = link->data;
MetaWindow *window = l->data;
if (window &&
window != not_this_one &&
(window->unmaps_pending == 0) &&
!window->minimized &&
(window->input || window->take_focus) &&
(workspace == NULL ||
meta_window_located_on_workspace (window, workspace)))
if (!window)
continue;
if (window == not_this_one)
continue;
if (window->unmaps_pending > 0)
continue;
if (window->minimized)
continue;
if (!(window->input || window->take_focus))
continue;
if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
continue;
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
continue;
if (not_this_one != NULL)
{
if (not_this_one != NULL)
{
if (transient_parent == NULL &&
not_this_one->xtransient_for != None &&
not_this_one->xtransient_for == window->xwindow &&
(!must_be_at_point ||
window_contains_point (window, root_x, root_y)))
transient_parent = window;
if (transient_parent == NULL &&
meta_window_get_transient_for (not_this_one) == window)
transient_parent = window;
if (topmost_in_group == NULL &&
not_this_one_group != NULL &&
not_this_one_group == meta_window_get_group (window) &&
(!must_be_at_point ||
window_contains_point (window, root_x, root_y)))
topmost_in_group = window;
}
if (topmost_overall == NULL &&
window->type != META_WINDOW_DOCK &&
(!must_be_at_point ||
window_contains_point (window, root_x, root_y)))
topmost_overall = window;
/* We could try to bail out early here for efficiency in
* some cases, but it's just not worth the code.
*/
if (topmost_in_group == NULL &&
not_this_one_group != NULL &&
not_this_one_group == meta_window_get_group (window))
topmost_in_group = window;
}
link = link->next;
if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
topmost_overall = window;
/* We could try to bail out early here for efficiency in
* some cases, but it's just not worth the code.
*/
}
if (transient_parent)

View File

@ -38,12 +38,15 @@
#include "screen-private.h"
#include <meta/util.h>
#include "stack.h"
#include "iconcache.h"
#include <X11/Xutil.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#include "meta-wayland-types.h"
#include "x11/iconcache.h"
#include "x11/group-private.h"
#include "wayland/meta-wayland-types.h"
typedef struct _MetaWindowQueue MetaWindowQueue;
@ -62,13 +65,28 @@ typedef enum {
#define NUMBER_OF_QUEUES 3
typedef enum {
_NET_WM_BYPASS_COMPOSITOR_HINT_AUTO = 0,
_NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1,
_NET_WM_BYPASS_COMPOSITOR_HINT_OFF = 2,
} MetaBypassCompositorHintValue;
typedef enum
{
META_IS_CONFIGURE_REQUEST = 1 << 0,
META_DO_GRAVITY_ADJUST = 1 << 1,
META_IS_USER_ACTION = 1 << 2,
META_IS_MOVE_ACTION = 1 << 3,
META_IS_RESIZE_ACTION = 1 << 4,
META_IS_WAYLAND_RESIZE = 1 << 5
} MetaMoveResizeFlags;
typedef enum
{
META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1,
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
} MetaMoveResizeResultFlags;
struct _MetaWindow
{
@ -85,19 +103,16 @@ struct _MetaWindow
MetaFrame *frame;
int depth;
Visual *xvisual;
Colormap colormap;
char *desc; /* used in debug spew */
char *title;
char *icon_name;
GdkPixbuf *icon;
GdkPixbuf *mini_icon;
MetaIconCache icon_cache;
Pixmap wm_hints_pixmap;
Pixmap wm_hints_mask;
MetaWindowType type;
Atom type_atom;
/* NOTE these five are not in UTF-8, we just treat them as random
* binary data
@ -159,8 +174,8 @@ struct _MetaWindow
/* Whether we're fullscreen */
guint fullscreen : 1;
/* Whether the urgent flag of WM_HINTS is set */
guint wm_hints_urgent : 1;
/* Whether the window is marked as urgent */
guint urgent : 1;
/* Whether we have to fullscreen after placement */
guint fullscreen_after_placement : 1;
@ -262,13 +277,6 @@ struct _MetaWindow
guint has_move_func : 1;
guint has_resize_func : 1;
guint has_fullscreen_func : 1;
/* Weird "_NET_WM_STATE_MODAL" flag */
guint wm_state_modal : 1;
/* TRUE if the client forced these on */
guint wm_state_skip_taskbar : 1;
guint wm_state_skip_pager : 1;
/* Computed whether to skip taskbar or not */
guint skip_taskbar : 1;
@ -322,15 +330,6 @@ struct _MetaWindow
/* Transient parent is a root window */
guint transient_parent_is_root_window : 1;
/* Info on which props we got our attributes from */
guint using_net_wm_name : 1; /* vs. plain wm_name */
guint using_net_wm_visible_name : 1; /* tracked so we can clear it */
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
/* icon props have changed */
guint need_reread_icon : 1;
/* if TRUE, window was maximized at start of current grab op */
guint shaken_loose : 1;
@ -431,8 +430,6 @@ struct _MetaWindow
* gives the position and size of the client window (i.e. ignoring
* the frame).
*
* Position valid if user_has_moved, size valid if user_has_resized
*
* Position always in root coords, unlike window->rect.
*/
MetaRectangle user_rect;
@ -471,10 +468,24 @@ struct _MetaWindowClass
{
GObjectClass parent_class;
void (*workspace_changed) (MetaWindow *window, int old_workspace);
void (*focus) (MetaWindow *window);
void (*raised) (MetaWindow *window);
void (*unmanaged) (MetaWindow *window);
void (*manage) (MetaWindow *window);
void (*unmanage) (MetaWindow *window);
void (*ping) (MetaWindow *window,
guint32 serial);
void (*delete) (MetaWindow *window,
guint32 timestamp);
void (*kill) (MetaWindow *window);
void (*focus) (MetaWindow *window,
guint32 timestamp);
void (*move_resize_internal) (MetaWindow *window,
int gravity,
MetaRectangle requested_rect,
MetaRectangle constrained_rect,
MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result);
void (*get_default_skip_hints) (MetaWindow *window,
gboolean *skip_taskbar_out,
gboolean *skip_pager_out);
};
/* These differ from window->has_foo_func in that they consider
@ -567,9 +578,6 @@ void meta_window_change_workspace (MetaWindow *window,
/* Return whether the window should be currently mapped */
gboolean meta_window_should_be_showing (MetaWindow *window);
/* See warning in window.c about this function */
gboolean __window_is_terminal (MetaWindow *window);
void meta_window_update_struts (MetaWindow *window);
/* this gets root coords */
@ -603,12 +611,6 @@ void meta_window_get_geometry (MetaWindow *window,
void meta_window_update_unfocused_button_grabs (MetaWindow *window);
/* Sends a client message */
void meta_window_send_icccm_message (MetaWindow *window,
Atom atom,
guint32 timestamp);
void meta_window_move_resize_request(MetaWindow *window,
guint value_mask,
int gravity,
@ -634,12 +636,6 @@ void meta_window_show_menu (MetaWindow *window,
int button,
guint32 timestamp);
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
void meta_window_shove_titlebar_onscreen (MetaWindow *window);
void meta_window_set_gravity (MetaWindow *window,
int gravity);
#ifdef HAVE_XSYNC
void meta_window_update_sync_request_counter (MetaWindow *window,
gint64 new_counter_value);
@ -684,9 +680,8 @@ void meta_window_update_layer (MetaWindow *window);
void meta_window_recalc_features (MetaWindow *window);
/* recalc_window_type is x11 only, wayland does its thing and then calls type_changed */
void meta_window_recalc_window_type (MetaWindow *window);
void meta_window_type_changed (MetaWindow *window);
void meta_window_set_type (MetaWindow *window,
MetaWindowType type);
void meta_window_frame_size_changed (MetaWindow *window);
@ -743,9 +738,24 @@ void meta_window_set_surface_mapped (MetaWindow *window,
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
void meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect);
void meta_window_activate_full (MetaWindow *window,
guint32 timestamp,
MetaClientType source_indication,
MetaWorkspace *workspace);
gboolean meta_window_is_client_decorated (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window);
void meta_window_set_urgent (MetaWindow *window,
gboolean urgent);
void meta_window_update_resize (MetaWindow *window,
gboolean snap,
int x, int y,
gboolean force);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -91,7 +91,6 @@ item(hotplug_mode_update)
item(_NET_WM_SYNC_REQUEST)
item(_NET_WM_SYNC_REQUEST_COUNTER)
item(_NET_WM_VISIBLE_NAME)
item(_NET_WM_VISIBLE_ICON_NAME)
item(_NET_SUPPORTING_WM_CHECK)
/* But I suppose it's quite reasonable not to advertise using
@ -132,7 +131,6 @@ item(_NET_CLIENT_LIST)
item(_NET_CLIENT_LIST_STACKING)
item(_NET_WM_STATE_SKIP_TASKBAR)
item(_NET_WM_STATE_SKIP_PAGER)
item(_NET_WM_ICON_NAME)
item(_NET_WM_ICON)
item(_NET_WM_ICON_GEOMETRY)
item(_NET_WM_MOVERESIZE)

View File

@ -163,13 +163,6 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
* @META_GRAB_OP_KEYBOARD_RESIZING_NE: Resizing NE with keyboard
* @META_GRAB_OP_KEYBOARD_RESIZING_SW: Resizing SW with keyboard
* @META_GRAB_OP_KEYBOARD_RESIZING_NW: Resizing NS with keyboard
* @META_GRAB_OP_KEYBOARD_TABBING_NORMAL: Tabbing
* @META_GRAB_OP_KEYBOARD_TABBING_DOCK: Tabbing through docks
* @META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: Escaping
* @META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: Escaping through docks
* @META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: Escaping through groups
* @META_GRAB_OP_KEYBOARD_TABBING_GROUP: Tabbing through groups
* @META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: Switch to another workspace
* @META_GRAB_OP_CLICKING_MINIMIZE: Clicked minimize button
* @META_GRAB_OP_CLICKING_MAXIMIZE: Clicked maximize button
* @META_GRAB_OP_CLICKING_UNMAXIMIZE: Clicked unmaximize button
@ -214,21 +207,6 @@ typedef enum
META_GRAB_OP_KEYBOARD_RESIZING_SW,
META_GRAB_OP_KEYBOARD_RESIZING_NW,
/* Alt+Tab */
META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
META_GRAB_OP_KEYBOARD_TABBING_DOCK,
/* Alt+Esc */
META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL,
META_GRAB_OP_KEYBOARD_ESCAPING_DOCK,
META_GRAB_OP_KEYBOARD_ESCAPING_GROUP,
/* Alt+F6 */
META_GRAB_OP_KEYBOARD_TABBING_GROUP,
META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING,
/* Frame button ops */
META_GRAB_OP_CLICKING_MINIMIZE,
META_GRAB_OP_CLICKING_MAXIMIZE,
@ -243,7 +221,10 @@ typedef enum
META_GRAB_OP_CLICKING_UNSTICK,
/* Special grab op when the compositor asked for a grab */
META_GRAB_OP_COMPOSITOR
META_GRAB_OP_COMPOSITOR,
/* For when a client takes a popup grab */
META_GRAB_OP_WAYLAND_CLIENT,
} MetaGrabOp;
/**

View File

@ -66,6 +66,8 @@ void meta_compositor_window_shape_changed (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_window_surface_changed (MetaCompositor *compositor,
MetaWindow *window);
gboolean meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,

View File

@ -163,10 +163,6 @@ void meta_display_set_input_focus_window (MetaDisplay *display,
gboolean focus_frame,
guint32 timestamp);
void meta_display_request_take_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp);
/* meta_display_focus_the_no_focus_window is called when the
* designated no_focus_window should be focused, but is otherwise the
* same as meta_display_set_input_focus_window
@ -178,8 +174,6 @@ void meta_display_focus_the_no_focus_window (MetaDisplay *display,
GSList *meta_display_sort_windows_by_stacking (MetaDisplay *display,
GSList *windows);
Window meta_display_get_leader_window (MetaDisplay *display);
void meta_display_add_ignored_crossing_serial (MetaDisplay *display,
unsigned long serial);

View File

@ -28,6 +28,7 @@ GOptionContext *meta_get_option_context (void);
void meta_init (void);
int meta_run (void);
void meta_register_with_session (void);
gboolean meta_activate_session (void);
gboolean meta_get_replace_current_wm (void); /* Actually defined in util.c */
void meta_set_wm_name (const char *wm_name);

View File

@ -254,9 +254,6 @@ struct _MetaPluginInfo
GType meta_plugin_get_type (void);
gboolean meta_plugin_running (MetaPlugin *plugin);
gboolean meta_plugin_debug_mode (MetaPlugin *plugin);
const MetaPluginInfo * meta_plugin_get_info (MetaPlugin *plugin);
/**
@ -408,8 +405,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
MetaScreen *meta_plugin_get_screen (MetaPlugin *plugin);
void
_meta_plugin_effect_started (MetaPlugin *plugin);
void _meta_plugin_set_screen (MetaPlugin *plugin, MetaScreen *screen);
/* XXX: Putting this in here so it's in the public header. */
void meta_plugin_manager_set_plugin_type (GType gtype);

View File

@ -62,7 +62,6 @@
* @META_PREF_EDGE_TILING: edge tiling
* @META_PREF_FORCE_FULLSCREEN: force fullscreen
* @META_PREF_WORKSPACES_ONLY_ON_PRIMARY: workspaces only on primary
* @META_PREF_NO_TAB_POPUP: no tab popup
* @META_PREF_DRAGGABLE_BORDER_WIDTH: draggable border width
* @META_PREF_AUTO_MAXIMIZE: auto-maximize
*/
@ -100,7 +99,6 @@ typedef enum
META_PREF_EDGE_TILING,
META_PREF_FORCE_FULLSCREEN,
META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
META_PREF_NO_TAB_POPUP,
META_PREF_DRAGGABLE_BORDER_WIDTH,
META_PREF_AUTO_MAXIMIZE
} MetaPreference;
@ -163,9 +161,6 @@ void meta_prefs_set_force_fullscreen (gboolean whether);
gboolean meta_prefs_get_workspaces_only_on_primary (void);
gboolean meta_prefs_get_no_tab_popup (void);
void meta_prefs_set_no_tab_popup (gboolean whether);
int meta_prefs_get_draggable_border_width (void);
gboolean meta_prefs_get_ignore_request_hide_titlebar (void);
@ -204,8 +199,6 @@ void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
* @META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: FILLME
* @META_KEYBINDING_ACTION_CYCLE_PANELS: FILLME
* @META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: FILLME
* @META_KEYBINDING_ACTION_TAB_POPUP_SELECT: FILLME
* @META_KEYBINDING_ACTION_TAB_POPUP_CANCEL: FILLME
* @META_KEYBINDING_ACTION_SHOW_DESKTOP: FILLME
* @META_KEYBINDING_ACTION_PANEL_MAIN_MENU: FILLME
* @META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: FILLME
@ -301,8 +294,6 @@ typedef enum _MetaKeyBindingAction
META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD,
META_KEYBINDING_ACTION_CYCLE_PANELS,
META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
META_KEYBINDING_ACTION_TAB_POPUP_SELECT,
META_KEYBINDING_ACTION_TAB_POPUP_CANCEL,
META_KEYBINDING_ACTION_SHOW_DESKTOP,
META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
@ -380,20 +371,6 @@ typedef enum
META_KEY_BINDING_IS_REVERSED = 1 << 3
} MetaKeyBindingFlags;
/**
* MetaKeyCombo:
* @keysym: keysym
* @keycode: keycode
* @modifiers: modifiers
*/
typedef struct _MetaKeyCombo MetaKeyCombo;
struct _MetaKeyCombo
{
unsigned int keysym;
unsigned int keycode;
MetaVirtualModifier modifiers;
};
/**
* MetaKeyHandlerFunc:
* @display: a #MetaDisplay
@ -411,45 +388,14 @@ typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
MetaKeyBinding *binding,
gpointer user_data);
typedef struct _MetaKeyHandler MetaKeyHandler;
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 *bindings;
/* 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;
GType meta_key_binding_get_type (void);
GList *meta_prefs_get_keybindings (void);
MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name);
void meta_prefs_get_window_binding (const char *name,
unsigned int *keysym,
MetaVirtualModifier *modifiers);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void);
gboolean meta_prefs_get_visual_bell (void);
gboolean meta_prefs_bell_is_audible (void);
GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);

View File

@ -72,11 +72,13 @@ typedef enum
* MetaMaximizeFlags:
* @META_MAXIMIZE_HORIZONTAL: Horizontal
* @META_MAXIMIZE_VERTICAL: Vertical
* @META_MAXIMIZE_BOTH: Both
*/
typedef enum
{
META_MAXIMIZE_HORIZONTAL = 1 << 0,
META_MAXIMIZE_VERTICAL = 1 << 1
META_MAXIMIZE_VERTICAL = 1 << 1,
META_MAXIMIZE_BOTH = (1 << 0 | 1 << 1),
} MetaMaximizeFlags;
/**
@ -123,7 +125,6 @@ MetaScreen *meta_window_get_screen (MetaWindow *window);
MetaDisplay *meta_window_get_display (MetaWindow *window);
Window meta_window_get_xwindow (MetaWindow *window);
MetaWindowType meta_window_get_window_type (MetaWindow *window);
Atom meta_window_get_window_type_atom (MetaWindow *window);
MetaWorkspace *meta_window_get_workspace (MetaWindow *window);
int meta_window_get_monitor (MetaWindow *window);
gboolean meta_window_is_on_all_workspaces (MetaWindow *window);
@ -163,7 +164,6 @@ void meta_window_change_workspace (MetaWindow *window,
MetaWorkspace *workspace);
GObject *meta_window_get_compositor_private (MetaWindow *window);
void meta_window_set_compositor_private (MetaWindow *window, GObject *priv);
void meta_window_configure_notify (MetaWindow *window, XConfigureEvent *event);
const char *meta_window_get_role (MetaWindow *window);
MetaStackLayer meta_window_get_layer (MetaWindow *window);
MetaWindow* meta_window_find_root_ancestor (MetaWindow *window);
@ -203,7 +203,6 @@ void meta_window_raise (MetaWindow *window);
void meta_window_lower (MetaWindow *window);
const char *meta_window_get_title (MetaWindow *window);
MetaWindow *meta_window_get_transient_for (MetaWindow *window);
Window meta_window_get_transient_for_as_xid (MetaWindow *window);
void meta_window_delete (MetaWindow *window,
guint32 timestamp);
guint meta_window_get_stable_sequence (MetaWindow *window);
@ -211,7 +210,6 @@ guint32 meta_window_get_user_time (MetaWindow *window);
int meta_window_get_pid (MetaWindow *window);
const char *meta_window_get_client_machine (MetaWindow *window);
gboolean meta_window_is_remote (MetaWindow *window);
gboolean meta_window_is_modal (MetaWindow *window);
gboolean meta_window_is_attached_dialog (MetaWindow *window);
const char *meta_window_get_mutter_hints (MetaWindow *window);
@ -252,6 +250,16 @@ void meta_window_begin_grab_op (MetaWindow *window,
gboolean frame_action,
guint32 timestamp);
gboolean meta_window_can_maximize (MetaWindow *window);
gboolean meta_window_can_minimize (MetaWindow *window);
gboolean meta_window_can_shade (MetaWindow *window);
gboolean meta_window_can_close (MetaWindow *window);
gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
gboolean meta_window_is_above (MetaWindow *window);
gboolean meta_window_allows_move (MetaWindow *window);
gboolean meta_window_allows_resize (MetaWindow *window);
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
void meta_window_shove_titlebar_onscreen (MetaWindow *window);
#endif

View File

@ -1,7 +1,7 @@
[Desktop Entry]
Type=Application
_Name=Mutter (wayland compositor)
Exec=mutter-launch -- mutter --wayland
Exec=mutter-launch -- mutter --wayland --display-server
NoDisplay=true
# name of loadable control center module
X-GNOME-WMSettingsModule=metacity

View File

@ -2,31 +2,31 @@
<schema id="org.gnome.mutter.wayland.keybindings" path="/org/gnome/mutter/wayland/keybindings/"
gettext-domain="@GETTEXT_DOMAIN@">
<key name="switch-to-session-1" type="as">
<default><![CDATA[['<Primary><Alt>F1', 'XF86Switch_VT_1']]]></default>
<default><![CDATA[['<Primary><Alt>F1']]]></default>
<_summary>Switch to VT 1</_summary>
</key>
<key name="switch-to-session-2" type="as">
<default><![CDATA[['<Primary><Alt>F2', 'XF86Switch_VT_2']]]></default>
<default><![CDATA[['<Primary><Alt>F2']]]></default>
<_summary>Switch to VT 2</_summary>
</key>
<key name="switch-to-session-3" type="as">
<default><![CDATA[['<Primary><Alt>F3', 'XF86Switch_VT_3']]]></default>
<default><![CDATA[['<Primary><Alt>F3']]]></default>
<_summary>Switch to VT 3</_summary>
</key>
<key name="switch-to-session-4" type="as">
<default><![CDATA[['<Primary><Alt>F4', 'XF86Switch_VT_4']]]></default>
<default><![CDATA[['<Primary><Alt>F4']]]></default>
<_summary>Switch to VT 4</_summary>
</key>
<key name="switch-to-session-5" type="as">
<default><![CDATA[['<Primary><Alt>F5', 'XF86Switch_VT_5']]]></default>
<default><![CDATA[['<Primary><Alt>F5']]]></default>
<_summary>Switch to VT 5</_summary>
</key>
<key name="switch-to-session-6" type="as">
<default><![CDATA[['<Primary><Alt>F6', 'XF86Switch_VT_6']]]></default>
<default><![CDATA[['<Primary><Alt>F6']]]></default>
<_summary>Switch to VT 6</_summary>
</key>
<key name="switch-to-session-7" type="as">
<default><![CDATA[['<Primary><Alt>F7', 'XF86Switch_VT_7']]]></default>
<default><![CDATA[['<Primary><Alt>F7']]]></default>
<_summary>Switch to VT 7</_summary>
</key>
</schema>

View File

@ -1,109 +0,0 @@
#! /bin/bash
if test -z "$XNEST_DISPLAY"; then
XNEST_DISPLAY=:8
fi
if test -z "$CLIENT_DISPLAY"; then
CLIENT_DISPLAY=:8
fi
if test -z "$MUTTER_DISPLAY"; then
export MUTTER_DISPLAY=$CLIENT_DISPLAY
fi
if test -z "$SCREENS"; then
SCREENS=1
fi
MAX_SCREEN=`echo $SCREENS-1 | bc`
if test "$DEBUG" = none; then
DEBUG=
elif test -z "$DEBUG"; then
DEBUG=
fi
if test -z "$CLIENTS"; then
CLIENTS=0
fi
if test -z "$SM_CLIENTS"; then
SM_CLIENTS=0
fi
if test -n "$EVIL_TEST"; then
TEST_CLIENT='./wm-tester/wm-tester --evil'
fi
if test -n "$ICON_TEST"; then
TEST_CLIENT='./wm-tester/wm-tester --icon-windows'
fi
if test -n "$DEMO_TEST"; then
TEST_CLIENT='./tools/mutter-window-demo'
fi
if test -n "$XINERAMA"; then
XINERAMA_FLAGS='+xinerama'
fi
export EF_ALLOW_MALLOC_0=1
if test -z "$ONLY_WM"; then
echo "Launching Xnest"
Xnest -ac $XNEST_DISPLAY -scrns $SCREENS -geometry 640x480 -bw 15 $XINERAMA_FLAGS &
## usleep 800000
sleep 1
if test -n "$XMON_DIR"; then
echo "Launching xmond"
$XMON_DIR/xmonui | $XMON_DIR/xmond -server localhost:$XNEST_DISPLAY &
sleep 1
fi
if test -n "$XSCOPE_DIR"; then
## xscope doesn't like to die when it should, it backgrounds itself
killall -9 xscope
killall -9 xscope
echo "Launching xscope"
DISPLAY= $XSCOPE_DIR/xscope -o1 -i28 > xscoped-replies.txt &
export MUTTER_DISPLAY=localhost:28
sleep 1
fi
echo "Launching clients"
if test -n "$TEST_CLIENT"; then
for I in `seq 0 $MAX_SCREEN`; do
DISPLAY=$CLIENT_DISPLAY.$I $TEST_CLIENT &
done
fi
if test $CLIENTS != 0; then
for I in `seq 1 $CLIENTS`; do
echo "Launching xterm $I"
DISPLAY=$CLIENT_DISPLAY xterm -geometry 25x15 &
done
fi
if test $SM_CLIENTS != 0; then
for I in `seq 1 $SM_CLIENTS`; do
echo "Launching gnome-terminal $I"
DISPLAY=$CLIENT_DISPLAY gnome-terminal --geometry 25x15 &
done
fi
if test -e ~/.Xmodmap; then
DISPLAY=$CLIENT_DISPLAY xmodmap ~/.Xmodmap
fi
usleep 50000
for I in `seq 0 $MAX_SCREEN`; do
DISPLAY=$CLIENT_DISPLAY.$I xsetroot -solid royalblue3
done
fi
if test -z "$ONLY_SETUP"; then
MUTTER_VERBOSE=1 MUTTER_USE_LOGFILE=1 MUTTER_DEBUG_BUTTON_GRABS=1 exec $DEBUG ./mutter $OPTIONS
fi

View File

@ -1,224 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Draw a workspace */
/* This file should not be modified to depend on other files in
* libwnck or mutter, since it's used in both of them
*/
/*
* Copyright (C) 2002 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "draw-workspace.h"
#include "theme-private.h"
static void
get_window_rect (const WnckWindowDisplayInfo *win,
int screen_width,
int screen_height,
const GdkRectangle *workspace_rect,
GdkRectangle *rect)
{
double width_ratio, height_ratio;
int x, y, width, height;
width_ratio = (double) workspace_rect->width / (double) screen_width;
height_ratio = (double) workspace_rect->height / (double) screen_height;
x = win->x;
y = win->y;
width = win->width;
height = win->height;
x *= width_ratio;
y *= height_ratio;
width *= width_ratio;
height *= height_ratio;
x += workspace_rect->x;
y += workspace_rect->y;
if (width < 3)
width = 3;
if (height < 3)
height = 3;
rect->x = x;
rect->y = y;
rect->width = width;
rect->height = height;
}
static void
draw_window (GtkWidget *widget,
cairo_t *cr,
const WnckWindowDisplayInfo *win,
const GdkRectangle *winrect,
GtkStateFlags state)
{
GdkPixbuf *icon;
int icon_x, icon_y, icon_w, icon_h;
gboolean is_active;
GdkRGBA color;
GtkStyleContext *style;
is_active = win->is_active;
cairo_save (cr);
cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height);
cairo_clip (cr);
style = gtk_widget_get_style_context (widget);
if (is_active)
meta_gtk_style_get_light_color (style, state, &color);
else
gtk_style_context_get_background_color (style, state, &color);
gdk_cairo_set_source_rgba (cr, &color);
cairo_rectangle (cr,
winrect->x + 1, winrect->y + 1,
MAX (0, winrect->width - 2), MAX (0, winrect->height - 2));
cairo_fill (cr);
icon = win->icon;
icon_w = icon_h = 0;
if (icon)
{
icon_w = gdk_pixbuf_get_width (icon);
icon_h = gdk_pixbuf_get_height (icon);
/* If the icon is too big, fall back to mini icon.
* We don't arbitrarily scale the icon, because it's
* just too slow on my Athlon 850.
*/
if (icon_w > (winrect->width - 2) ||
icon_h > (winrect->height - 2))
{
icon = win->mini_icon;
if (icon)
{
icon_w = gdk_pixbuf_get_width (icon);
icon_h = gdk_pixbuf_get_height (icon);
/* Give up. */
if (icon_w > (winrect->width - 2) ||
icon_h > (winrect->height - 2))
icon = NULL;
}
}
}
if (icon)
{
icon_x = winrect->x + (winrect->width - icon_w) / 2;
icon_y = winrect->y + (winrect->height - icon_h) / 2;
cairo_save (cr);
gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y);
cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h);
cairo_clip (cr);
cairo_paint (cr);
cairo_restore (cr);
}
gtk_style_context_get_color (style, state, &color);
gdk_cairo_set_source_rgba (cr, &color);
cairo_set_line_width (cr, 1.0);
cairo_rectangle (cr,
winrect->x + 0.5, winrect->y + 0.5,
MAX (0, winrect->width - 1), MAX (0, winrect->height - 1));
cairo_stroke (cr);
cairo_restore (cr);
}
void
wnck_draw_workspace (GtkWidget *widget,
cairo_t *cr,
int x,
int y,
int width,
int height,
int screen_width,
int screen_height,
GdkPixbuf *workspace_background,
gboolean is_active,
const WnckWindowDisplayInfo *windows,
int n_windows)
{
int i;
GdkRectangle workspace_rect;
GtkStateFlags state;
GtkStyleContext *style;
workspace_rect.x = x;
workspace_rect.y = y;
workspace_rect.width = width;
workspace_rect.height = height;
if (is_active)
state = GTK_STATE_FLAG_SELECTED;
else if (workspace_background)
state = GTK_STATE_FLAG_PRELIGHT;
else
state = GTK_STATE_FLAG_NORMAL;
style = gtk_widget_get_style_context (widget);
cairo_save (cr);
if (workspace_background)
{
gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y);
cairo_paint (cr);
}
else
{
GdkRGBA color;
meta_gtk_style_get_dark_color (style,state, &color);
gdk_cairo_set_source_rgba (cr, &color);
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
}
i = 0;
while (i < n_windows)
{
const WnckWindowDisplayInfo *win = &windows[i];
GdkRectangle winrect;
get_window_rect (win, screen_width,
screen_height, &workspace_rect, &winrect);
draw_window (widget,
cr,
win,
&winrect,
state);
++i;
}
cairo_restore (cr);
}

View File

@ -1,59 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Draw a workspace */
/* This file should not be modified to depend on other files in
* libwnck or metacity, since it's used in both of them
*/
/*
* Copyright (C) 2002 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WNCK_DRAW_WORKSPACE_H
#define WNCK_DRAW_WORKSPACE_H
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>
typedef struct
{
GdkPixbuf *icon;
GdkPixbuf *mini_icon;
int x;
int y;
int width;
int height;
guint is_active : 1;
} WnckWindowDisplayInfo;
void wnck_draw_workspace (GtkWidget *widget,
cairo_t *cr,
int x,
int y,
int width,
int height,
int screen_width,
int screen_height,
GdkPixbuf *workspace_background,
gboolean is_active,
const WnckWindowDisplayInfo *windows,
int n_windows);
#endif

View File

@ -44,8 +44,6 @@
static void meta_frames_destroy (GtkWidget *object);
static void meta_frames_finalize (GObject *object);
static void meta_frames_style_updated (GtkWidget *widget);
static void meta_frames_map (GtkWidget *widget);
static void meta_frames_unmap (GtkWidget *widget);
static void meta_frames_update_prelit_control (MetaFrames *frames,
MetaUIFrame *frame,
@ -134,9 +132,6 @@ meta_frames_class_init (MetaFramesClass *class)
widget_class->style_updated = meta_frames_style_updated;
widget_class->map = meta_frames_map;
widget_class->unmap = meta_frames_unmap;
widget_class->draw = meta_frames_draw;
widget_class->destroy_event = meta_frames_destroy_event;
widget_class->button_press_event = meta_frames_button_press_event;
@ -231,6 +226,7 @@ meta_frames_init (MetaFrames *frames)
frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
update_style_contexts (frames);
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
@ -522,13 +518,26 @@ MetaFrames*
meta_frames_new (int screen_number)
{
GdkScreen *screen;
MetaFrames *frames;
screen = gdk_display_get_screen (gdk_display_get_default (),
screen_number);
return g_object_new (META_TYPE_FRAMES,
"screen", screen,
NULL);
frames = g_object_new (META_TYPE_FRAMES,
"screen", screen,
"type", GTK_WINDOW_POPUP,
NULL);
/* Put the window at an arbitrary offscreen location; the one place
* it can't be is at -100x-100, since the meta_window_new() will
* mistake it for a window created via meta_create_offscreen_window()
* and ignore it, and we need this window to get frame-synchronization
* messages so that GTK+'s style change handling works.
*/
gtk_window_move (GTK_WINDOW (frames), -200, -200);
gtk_window_resize (GTK_WINDOW (frames), 1, 1);
return frames;
}
/* In order to use a style with a window it has to be attached to that
@ -635,22 +644,6 @@ meta_frames_unmanage_window (MetaFrames *frames,
meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
}
static void
meta_frames_map (GtkWidget *widget)
{
/* We override the parent map function to a no-op because we don't
* want to actually show the GDK window. But GTK needs to think that
* the widget is mapped or it won't deliver the events we care about.
*/
gtk_widget_set_mapped (widget, TRUE);
}
static void
meta_frames_unmap (GtkWidget *widget)
{
gtk_widget_set_mapped (widget, FALSE);
}
static MetaUIFrame*
meta_frames_lookup_window (MetaFrames *frames,
Window xwindow)

View File

@ -1,963 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Mutter popup window thing showing windows you can tab to */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2002 Red Hat, Inc.
* Copyright (C) 2005 Elijah Newren
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <meta/util.h>
#include "core.h"
#include "tabpopup.h"
/* FIXME these two includes are 100% broken ...
*/
#include "workspace-private.h"
#include "frame.h"
#include "draw-workspace.h"
#include <gtk/gtk.h>
#include <math.h>
#define OUTSIDE_SELECT_RECT 2
#define INSIDE_SELECT_RECT 2
typedef struct _TabEntry TabEntry;
struct _TabEntry
{
MetaTabEntryKey key;
char *title;
GdkPixbuf *icon, *dimmed_icon;
GtkWidget *widget;
GdkRectangle rect;
GdkRectangle inner_rect;
guint blank : 1;
};
struct _MetaTabPopup
{
GtkWidget *window;
GtkWidget *label;
GList *current;
GList *entries;
TabEntry *current_selected_entry;
GtkWidget *outline_window;
gboolean outline;
};
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
static void select_image (GtkWidget *widget);
static void unselect_image (GtkWidget *widget);
static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace);
static void select_workspace (GtkWidget *widget);
static void unselect_workspace (GtkWidget *widget);
static gboolean
outline_window_draw (GtkWidget *widget,
cairo_t *cr,
gpointer data)
{
MetaTabPopup *popup;
TabEntry *te;
popup = data;
if (!popup->outline || popup->current_selected_entry == NULL)
return FALSE;
te = popup->current_selected_entry;
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
cairo_rectangle (cr,
0.5, 0.5,
te->rect.width - 1,
te->rect.height - 1);
cairo_stroke (cr);
cairo_rectangle (cr,
te->inner_rect.x - 0.5, te->inner_rect.y - 0.5,
te->inner_rect.width + 1,
te->inner_rect.height + 1);
cairo_stroke (cr);
return FALSE;
}
static GdkPixbuf*
dimm_icon (GdkPixbuf *pixbuf)
{
int x, y, pixel_stride, row_stride;
guchar *row, *pixels;
int w, h;
GdkPixbuf *dimmed_pixbuf;
if (gdk_pixbuf_get_has_alpha (pixbuf))
{
dimmed_pixbuf = gdk_pixbuf_copy (pixbuf);
}
else
{
dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
}
w = gdk_pixbuf_get_width (dimmed_pixbuf);
h = gdk_pixbuf_get_height (dimmed_pixbuf);
pixel_stride = 4;
row = gdk_pixbuf_get_pixels (dimmed_pixbuf);
row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf);
for (y = 0; y < h; y++)
{
pixels = row;
for (x = 0; x < w; x++)
{
pixels[3] /= 2;
pixels += pixel_stride;
}
row += row_stride;
}
return dimmed_pixbuf;
}
static TabEntry*
tab_entry_new (const MetaTabEntry *entry,
gint screen_width,
gboolean outline)
{
TabEntry *te;
te = g_new (TabEntry, 1);
te->key = entry->key;
te->title = NULL;
if (entry->title)
{
gchar *str;
gchar *tmp;
gchar *formatter = "%s";
str = meta_g_utf8_strndup (entry->title, 4096);
if (entry->hidden)
{
formatter = "[%s]";
}
tmp = g_markup_printf_escaped (formatter, str);
g_free (str);
str = tmp;
if (entry->demands_attention)
{
/* Escape the whole line of text then markup the text and
* copy it back into the original buffer.
*/
tmp = g_strdup_printf ("<b>%s</b>", str);
g_free (str);
str = tmp;
}
te->title=g_strdup(str);
g_free (str);
}
te->widget = NULL;
te->icon = entry->icon;
te->blank = entry->blank;
te->dimmed_icon = NULL;
if (te->icon)
{
g_object_ref (G_OBJECT (te->icon));
if (entry->hidden)
te->dimmed_icon = dimm_icon (entry->icon);
}
if (outline)
{
te->rect.x = entry->rect.x;
te->rect.y = entry->rect.y;
te->rect.width = entry->rect.width;
te->rect.height = entry->rect.height;
te->inner_rect.x = entry->inner_rect.x;
te->inner_rect.y = entry->inner_rect.y;
te->inner_rect.width = entry->inner_rect.width;
te->inner_rect.height = entry->inner_rect.height;
}
return te;
}
MetaTabPopup*
meta_ui_tab_popup_new (const MetaTabEntry *entries,
int screen_number,
int entry_count,
int width,
gboolean outline)
{
MetaTabPopup *popup;
int i, left, top;
int height;
GtkWidget *grid;
GtkWidget *vbox;
GtkWidget *align;
GList *tmp;
GtkWidget *frame;
int max_label_width; /* the actual max width of the labels we create */
AtkObject *obj;
GdkScreen *screen;
int screen_width;
popup = g_new (MetaTabPopup, 1);
popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
screen = gdk_display_get_screen (gdk_display_get_default (),
screen_number);
gtk_window_set_screen (GTK_WINDOW (popup->outline_window),
screen);
gtk_widget_set_app_paintable (popup->outline_window, TRUE);
gtk_widget_realize (popup->outline_window);
g_signal_connect (G_OBJECT (popup->outline_window), "draw",
G_CALLBACK (outline_window_draw), popup);
popup->window = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_screen (GTK_WINDOW (popup->window),
screen);
gtk_window_set_position (GTK_WINDOW (popup->window),
GTK_WIN_POS_CENTER_ALWAYS);
/* enable resizing, to get never-shrink behavior */
gtk_window_set_resizable (GTK_WINDOW (popup->window),
TRUE);
popup->current = NULL;
popup->entries = NULL;
popup->current_selected_entry = NULL;
popup->outline = outline;
screen_width = gdk_screen_get_width (screen);
for (i = 0; i < entry_count; ++i)
{
TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline);
popup->entries = g_list_prepend (popup->entries, new_entry);
}
popup->entries = g_list_reverse (popup->entries);
g_assert (width > 0);
height = i / width;
if (i % width)
height += 1;
grid = gtk_grid_new ();
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
gtk_container_set_border_width (GTK_CONTAINER (grid), 1);
gtk_container_add (GTK_CONTAINER (popup->window),
frame);
gtk_container_add (GTK_CONTAINER (frame),
vbox);
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (align),
grid);
popup->label = gtk_label_new ("");
/* Set the accessible role of the label to a status bar so it
* will emit name changed events that can be used by screen
* readers.
*/
obj = gtk_widget_get_accessible (popup->label);
atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
max_label_width = 0;
top = 0;
tmp = popup->entries;
while (tmp && top < height)
{
left = 0;
while (tmp && left < width)
{
GtkWidget *image;
GtkRequisition req;
TabEntry *te;
te = tmp->data;
if (te->blank)
{
/* just stick a widget here to avoid special cases */
image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
}
else if (outline)
{
if (te->dimmed_icon)
{
image = selectable_image_new (te->dimmed_icon);
}
else
{
image = selectable_image_new (te->icon);
}
gtk_misc_set_padding (GTK_MISC (image),
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1,
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1);
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
}
else
{
image = selectable_workspace_new ((MetaWorkspace *) te->key);
}
te->widget = image;
gtk_grid_attach (GTK_GRID (grid),
te->widget,
left, top, 1, 1);
/* Efficiency rules! */
gtk_label_set_markup (GTK_LABEL (popup->label),
te->title);
gtk_widget_get_preferred_size (popup->label, &req, NULL);
max_label_width = MAX (max_label_width, req.width);
tmp = tmp->next;
++left;
}
++top;
}
/* remove all the temporary text */
gtk_label_set_text (GTK_LABEL (popup->label), "");
/* Make it so that we ellipsize if the text is too long */
gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END);
/* Limit the window size to no bigger than screen_width/4 */
if (max_label_width>(screen_width/4))
{
max_label_width = screen_width/4;
}
max_label_width += 20; /* add random padding */
gtk_window_set_default_size (GTK_WINDOW (popup->window),
max_label_width,
-1);
return popup;
}
static void
free_tab_entry (gpointer data, gpointer user_data)
{
TabEntry *te;
te = data;
g_free (te->title);
if (te->icon)
g_object_unref (G_OBJECT (te->icon));
if (te->dimmed_icon)
g_object_unref (G_OBJECT (te->dimmed_icon));
g_free (te);
}
void
meta_ui_tab_popup_free (MetaTabPopup *popup)
{
meta_verbose ("Destroying tab popup window\n");
if (!popup)
{
meta_warning ("NULL passed to meta_ui_tab_popup_free\n");
return;
}
gtk_widget_destroy (popup->outline_window);
gtk_widget_destroy (popup->window);
g_list_foreach (popup->entries, free_tab_entry, NULL);
g_list_free (popup->entries);
g_free (popup);
}
void
meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
gboolean showing)
{
if (showing)
{
gtk_widget_show_all (popup->window);
}
else
{
if (gtk_widget_get_visible (popup->window))
{
meta_verbose ("Hiding tab popup window\n");
gtk_widget_hide (popup->window);
meta_core_increment_event_serial (
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
}
}
}
static void
display_entry (MetaTabPopup *popup,
TabEntry *te)
{
GdkRectangle rect;
GdkWindow *window;
if (popup->current_selected_entry)
{
if (popup->outline)
unselect_image (popup->current_selected_entry->widget);
else
unselect_workspace (popup->current_selected_entry->widget);
}
gtk_label_set_markup (GTK_LABEL (popup->label), te->title);
if (popup->outline)
select_image (te->widget);
else
select_workspace (te->widget);
if (popup->outline)
{
cairo_region_t *region;
cairo_region_t *inner_region;
GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
window = gtk_widget_get_window (popup->outline_window);
/* Do stuff behind gtk's back */
gdk_window_hide (window);
meta_core_increment_event_serial (
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
rect = te->rect;
rect.x = 0;
rect.y = 0;
gdk_window_move_resize (window,
te->rect.x, te->rect.y,
te->rect.width, te->rect.height);
gdk_window_set_background_rgba (window, &black);
region = cairo_region_create_rectangle (&rect);
inner_region = cairo_region_create_rectangle (&te->inner_rect);
cairo_region_subtract (region, inner_region);
cairo_region_destroy (inner_region);
gdk_window_shape_combine_region (window,
region,
0, 0);
cairo_region_destroy (region);
/* This should piss off gtk a bit, but we don't want to raise
* above the tab popup. So, instead of calling gtk_widget_show,
* we manually set the window as mapped and then manually map it
* with gdk functions.
*/
gtk_widget_set_mapped (popup->outline_window, TRUE);
gdk_window_show_unraised (window);
}
/* Must be before we handle an expose for the outline window */
popup->current_selected_entry = te;
}
void
meta_ui_tab_popup_forward (MetaTabPopup *popup)
{
if (popup->current != NULL)
popup->current = popup->current->next;
if (popup->current == NULL)
popup->current = popup->entries;
if (popup->current != NULL)
{
TabEntry *te;
te = popup->current->data;
display_entry (popup, te);
}
}
void
meta_ui_tab_popup_backward (MetaTabPopup *popup)
{
if (popup->current != NULL)
popup->current = popup->current->prev;
if (popup->current == NULL)
popup->current = g_list_last (popup->entries);
if (popup->current != NULL)
{
TabEntry *te;
te = popup->current->data;
display_entry (popup, te);
}
}
MetaTabEntryKey
meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
{
if (popup->current)
{
TabEntry *te;
te = popup->current->data;
return te->key;
}
else
return (MetaTabEntryKey)None;
}
void
meta_ui_tab_popup_select (MetaTabPopup *popup,
MetaTabEntryKey key)
{
GList *tmp;
/* Note, "key" may not be in the list of entries; other code assumes
* it's OK to pass in a key that isn't.
*/
tmp = popup->entries;
while (tmp != NULL)
{
TabEntry *te;
te = tmp->data;
if (te->key == key)
{
popup->current = tmp;
display_entry (popup, te);
return;
}
tmp = tmp->next;
}
}
#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ())
#define META_SELECT_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage))
typedef struct _MetaSelectImage MetaSelectImage;
typedef struct _MetaSelectImageClass MetaSelectImageClass;
struct _MetaSelectImage
{
GtkImage parent_instance;
guint selected : 1;
};
struct _MetaSelectImageClass
{
GtkImageClass parent_class;
};
static GType meta_select_image_get_type (void) G_GNUC_CONST;
static GtkWidget*
selectable_image_new (GdkPixbuf *pixbuf)
{
GtkWidget *w;
w = g_object_new (meta_select_image_get_type (), NULL);
gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf);
return w;
}
static void
select_image (GtkWidget *widget)
{
META_SELECT_IMAGE (widget)->selected = TRUE;
gtk_widget_queue_draw (widget);
}
static void
unselect_image (GtkWidget *widget)
{
META_SELECT_IMAGE (widget)->selected = FALSE;
gtk_widget_queue_draw (widget);
}
static void meta_select_image_class_init (MetaSelectImageClass *klass);
static gboolean meta_select_image_draw (GtkWidget *widget,
cairo_t *cr);
static GtkImageClass *parent_class;
GType
meta_select_image_get_type (void)
{
static GType image_type = 0;
if (!image_type)
{
static const GTypeInfo image_info =
{
sizeof (MetaSelectImageClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) meta_select_image_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (MetaSelectImage),
16, /* n_preallocs */
(GInstanceInitFunc) NULL,
};
image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0);
}
return image_type;
}
static void
meta_select_image_class_init (MetaSelectImageClass *klass)
{
GtkWidgetClass *widget_class;
parent_class = g_type_class_peek (gtk_image_get_type ());
widget_class = GTK_WIDGET_CLASS (klass);
widget_class->draw = meta_select_image_draw;
}
static gboolean
meta_select_image_draw (GtkWidget *widget,
cairo_t *cr)
{
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
if (META_SELECT_IMAGE (widget)->selected)
{
GtkMisc *misc;
GtkRequisition requisition;
GtkStyleContext *context;
GdkRGBA color;
int x, y, w, h;
gint xpad, ypad;
gfloat xalign, yalign;
misc = GTK_MISC (widget);
gtk_widget_get_requisition (widget, &requisition);
gtk_misc_get_alignment (misc, &xalign, &yalign);
gtk_misc_get_padding (misc, &xpad, &ypad);
x = (allocation.width - (requisition.width - xpad * 2)) * xalign + 0.5;
y = (allocation.height - (requisition.height - ypad * 2)) * yalign + 0.5;
x -= INSIDE_SELECT_RECT + 1;
y -= INSIDE_SELECT_RECT + 1;
w = requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
h = requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
context = gtk_widget_get_style_context (widget);
gtk_style_context_set_state (context,
gtk_widget_get_state_flags (widget));
gtk_style_context_lookup_color (context, "color", &color);
cairo_set_line_width (cr, 2.0);
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
cairo_rectangle (cr, x, y, w + 1, h + 1);
cairo_stroke (cr);
cairo_set_line_width (cr, 1.0);
}
return GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);
}
#define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ())
#define META_SELECT_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace))
typedef struct _MetaSelectWorkspace MetaSelectWorkspace;
typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass;
struct _MetaSelectWorkspace
{
GtkDrawingArea parent_instance;
MetaWorkspace *workspace;
guint selected : 1;
};
struct _MetaSelectWorkspaceClass
{
GtkDrawingAreaClass parent_class;
};
static GType meta_select_workspace_get_type (void) G_GNUC_CONST;
#define SELECT_OUTLINE_WIDTH 2
#define MINI_WORKSPACE_WIDTH 48
static GtkWidget*
selectable_workspace_new (MetaWorkspace *workspace)
{
GtkWidget *widget;
double screen_aspect;
widget = g_object_new (meta_select_workspace_get_type (), NULL);
screen_aspect = (double) workspace->screen->rect.height /
(double) workspace->screen->rect.width;
/* account for select rect */
gtk_widget_set_size_request (widget,
MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2,
MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2);
META_SELECT_WORKSPACE (widget)->workspace = workspace;
return widget;
}
static void
select_workspace (GtkWidget *widget)
{
META_SELECT_WORKSPACE(widget)->selected = TRUE;
gtk_widget_queue_draw (widget);
}
static void
unselect_workspace (GtkWidget *widget)
{
META_SELECT_WORKSPACE (widget)->selected = FALSE;
gtk_widget_queue_draw (widget);
}
static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass);
static gboolean meta_select_workspace_draw (GtkWidget *widget,
cairo_t *cr);
GType
meta_select_workspace_get_type (void)
{
static GType workspace_type = 0;
if (!workspace_type)
{
static const GTypeInfo workspace_info =
{
sizeof (MetaSelectWorkspaceClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) meta_select_workspace_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (MetaSelectWorkspace),
16, /* n_preallocs */
(GInstanceInitFunc) NULL,
};
workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
"MetaSelectWorkspace",
&workspace_info,
0);
}
return workspace_type;
}
static void
meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass)
{
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_CLASS (klass);
widget_class->draw = meta_select_workspace_draw;
}
/**
* meta_convert_meta_to_wnck:
* @window: the #MetaWindow
* @screen: the #MetaScreen the window is on
*
* Converts a #MetaWindow to a #WnckWindowDisplayInfo window
* that is used to build a thumbnail of a workspace.
**/
static WnckWindowDisplayInfo
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
{
WnckWindowDisplayInfo wnck_window;
wnck_window.icon = window->icon;
wnck_window.mini_icon = window->mini_icon;
wnck_window.is_active = window->has_focus;
if (window->frame)
{
wnck_window.x = window->frame->rect.x;
wnck_window.y = window->frame->rect.y;
wnck_window.width = window->frame->rect.width;
wnck_window.height = window->frame->rect.height;
}
else
{
wnck_window.x = window->rect.x;
wnck_window.y = window->rect.y;
wnck_window.width = window->rect.width;
wnck_window.height = window->rect.height;
}
return wnck_window;
}
static gboolean
meta_select_workspace_draw (GtkWidget *widget,
cairo_t *cr)
{
MetaWorkspace *workspace;
WnckWindowDisplayInfo *windows;
GtkAllocation allocation;
int i, n_windows;
GList *tmp, *list;
workspace = META_SELECT_WORKSPACE (widget)->workspace;
list = meta_stack_list_windows (workspace->screen->stack, workspace);
n_windows = g_list_length (list);
windows = g_new (WnckWindowDisplayInfo, n_windows);
tmp = list;
i = 0;
while (tmp != NULL)
{
MetaWindow *window;
gboolean ignoreable_sticky;
window = tmp->data;
ignoreable_sticky = window->on_all_workspaces &&
workspace != workspace->screen->active_workspace;
if (window->skip_pager ||
!meta_window_showing_on_its_workspace (window) ||
window->unmaps_pending ||
ignoreable_sticky)
{
--n_windows;
}
else
{
windows[i] = meta_convert_meta_to_wnck (window, workspace->screen);
i++;
}
tmp = tmp->next;
}
g_list_free (list);
gtk_widget_get_allocation (widget, &allocation);
wnck_draw_workspace (widget,
cr,
SELECT_OUTLINE_WIDTH,
SELECT_OUTLINE_WIDTH,
allocation.width - SELECT_OUTLINE_WIDTH * 2,
allocation.height - SELECT_OUTLINE_WIDTH * 2,
workspace->screen->rect.width,
workspace->screen->rect.height,
NULL,
(workspace->screen->active_workspace == workspace),
windows,
n_windows);
g_free (windows);
if (META_SELECT_WORKSPACE (widget)->selected)
{
GtkStyleContext *context;
GdkRGBA color;
context = gtk_widget_get_style_context (widget);
gtk_style_context_set_state (context,
gtk_widget_get_state_flags (widget));
gtk_style_context_lookup_color (context, "color", &color);
cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH);
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
cairo_rectangle (cr,
SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0,
allocation.width - SELECT_OUTLINE_WIDTH,
allocation.height - SELECT_OUTLINE_WIDTH);
cairo_stroke (cr);
}
return TRUE;
}

View File

@ -1,65 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Mutter tab popup window */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2005 Elijah Newren
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_TABPOPUP_H
#define META_TABPOPUP_H
/* Don't include gtk.h or gdk.h here */
#include <meta/common.h>
#include <meta/boxes.h>
#include <X11/Xlib.h>
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef struct _MetaTabEntry MetaTabEntry;
typedef struct _MetaTabPopup MetaTabPopup;
typedef void *MetaTabEntryKey;
struct _MetaTabEntry
{
MetaTabEntryKey key;
const char *title;
GdkPixbuf *icon;
MetaRectangle rect;
MetaRectangle inner_rect;
guint blank : 1;
guint hidden : 1;
guint demands_attention : 1;
};
MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
int screen_number,
int entry_count,
int width,
gboolean outline);
void meta_ui_tab_popup_free (MetaTabPopup *popup);
void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
gboolean showing);
void meta_ui_tab_popup_forward (MetaTabPopup *popup);
void meta_ui_tab_popup_backward (MetaTabPopup *popup);
MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
void meta_ui_tab_popup_select (MetaTabPopup *popup,
MetaTabEntryKey key);
#endif

View File

@ -295,9 +295,12 @@ meta_ui_new (Display *xdisplay,
g_assert (gdisplay == gdk_display_get_default ());
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
/* This does not actually show any widget. MetaFrames has been hacked so
* that showing it doesn't actually do anything. But we need the flags
* set for GTK to deliver events properly. */
/* GTK+ needs the frame-sync protocol to work in order to properly
* handle style changes. This means that the dummy widget we create
* to get the style for title bars actually needs to be mapped
* and fully tracked as a MetaWindow. Horrible, but mostly harmless -
* the window is a 1x1 overide redirect window positioned offscreen.
*/
gtk_widget_show (GTK_WIDGET (ui->frames));
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);

View File

@ -178,6 +178,4 @@ int meta_ui_get_drag_threshold (MetaUI *ui);
MetaUIDirection meta_ui_get_direction (void);
#include "tabpopup.h"
#endif

View File

@ -48,7 +48,7 @@ data_offer_accept (struct wl_client *client,
* this be a wl_data_device request? */
if (offer->source)
offer->source->accept (offer->source, serial, mime_type);
wl_data_source_send_target (offer->source->resource, mime_type);
}
static void
@ -58,9 +58,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
if (offer->source)
offer->source->send (offer->source, mime_type, fd);
else
close (fd);
wl_data_source_send_send (offer->source->resource, mime_type, fd);
close (fd);
}
static void
@ -82,7 +82,8 @@ destroy_data_offer (struct wl_resource *resource)
if (offer->source)
wl_list_remove (&offer->source_destroy_listener.link);
free (offer);
g_slice_free (MetaWaylandDataOffer, offer);
}
static void
@ -99,13 +100,9 @@ static struct wl_resource *
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
struct wl_resource *target)
{
MetaWaylandDataOffer *offer;
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
char **p;
offer = malloc (sizeof *offer);
if (offer == NULL)
return NULL;
offer->source = source;
offer->source_destroy_listener.notify = destroy_offer_data_source;
@ -178,8 +175,7 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
static void
drag_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface,
const ClutterEvent *event)
MetaWaylandSurface *surface)
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
MetaWaylandSeat *seat = drag_grab->seat;
@ -260,7 +256,7 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
if (drag_grab->drag_data_source)
wl_list_remove (&drag_grab->drag_data_source_listener.link);
drag_grab_focus (&drag_grab->generic, NULL, NULL);
drag_grab_focus (&drag_grab->generic, NULL);
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
g_slice_free (MetaWaylandDragGrab, drag_grab);
@ -318,8 +314,12 @@ data_device_start_drag (struct wl_client *client,
{
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandDragGrab *drag_grab;
/* FIXME: Check that client has implicit grab on the origin
* surface that matches the given time. */
if ((seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial ||
!seat->pointer.focus_surface ||
seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource)))
return;
/* FIXME: Check that the data source type array isn't empty. */
@ -332,6 +332,7 @@ data_device_start_drag (struct wl_client *client,
drag_grab->generic.pointer = &seat->pointer;
drag_grab->drag_client = client;
drag_grab->seat = seat;
if (source_resource)
{
@ -375,7 +376,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
}
}
void
static void
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
MetaWaylandDataSource *source,
guint32 serial)
@ -389,7 +390,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
if (seat->selection_data_source)
{
seat->selection_data_source->cancel (seat->selection_data_source);
wl_data_source_send_cancelled (seat->selection_data_source->resource);
wl_list_remove (&seat->selection_data_source_listener.link);
seat->selection_data_source = NULL;
}
@ -449,47 +450,21 @@ static const struct wl_data_device_interface data_device_interface = {
static void
destroy_data_source (struct wl_resource *resource)
{
MetaWaylandDataSource *source = wl_container_of (resource, source, resource);
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
char **p;
wl_array_for_each (p, &source->mime_types) free (*p);
wl_array_release (&source->mime_types);
}
static void
client_source_accept (MetaWaylandDataSource *source,
guint32 time, const char *mime_type)
{
wl_data_source_send_target (source->resource, mime_type);
}
static void
client_source_send (MetaWaylandDataSource *source,
const char *mime_type, int32_t fd)
{
wl_data_source_send_send (source->resource, mime_type, fd);
close (fd);
}
static void
client_source_cancel (MetaWaylandDataSource *source)
{
wl_data_source_send_cancelled (source->resource);
g_slice_free (MetaWaylandDataSource, source);
}
static void
create_data_source (struct wl_client *client,
struct wl_resource *resource, guint32 id)
{
MetaWaylandDataSource *source;
source = malloc (sizeof *source);
if (source == NULL)
{
wl_resource_post_no_memory (resource);
return;
}
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
source->resource = wl_resource_create (client, &wl_data_source_interface,
MIN (META_WL_DATA_SOURCE_VERSION,
@ -497,10 +472,6 @@ create_data_source (struct wl_client *client,
wl_resource_set_implementation (source->resource, &data_source_interface,
source, destroy_data_source);
source->accept = client_source_accept;
source->send = client_source_send;
source->cancel = client_source_cancel;
wl_array_init (&source->mime_types);
}

View File

@ -33,10 +33,4 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
int
meta_wayland_data_device_manager_init (struct wl_display *display);
void
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
MetaWaylandDataSource *source,
uint32_t serial);
#endif /* __META_WAYLAND_DATA_DEVICE_H__ */

View File

@ -138,23 +138,11 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
return;
}
if (xkb_info->keymap)
xkb_keymap_unref (xkb_info->keymap);
xkb_keymap_unref (xkb_info->keymap);
xkb_info->keymap = keymap;
xkb_info->shift_mod =
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
xkb_info->caps_mod =
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CAPS);
xkb_info->ctrl_mod =
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CTRL);
xkb_info->alt_mod =
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_ALT);
xkb_info->mod2_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod2");
xkb_info->mod3_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod3");
xkb_info->super_mod =
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_LOGO);
xkb_info->mod5_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod5");
xkb_state_unref (xkb_info->state);
xkb_info->state = xkb_state_new (keymap);
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
if (keymap_str == NULL)
@ -222,7 +210,6 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
wl_list_remove (&keyboard->focus_surface_listener.link);
keyboard->focus_surface = NULL;
if (keyboard->focus_resource)
@ -237,7 +224,6 @@ keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data
{
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
wl_list_remove (&keyboard->focus_resource_listener.link);
keyboard->focus_resource = NULL;
}
@ -297,31 +283,6 @@ static const MetaWaylandKeyboardGrabInterface
default_grab_modifiers,
};
static gboolean
modal_key (MetaWaylandKeyboardGrab *grab,
uint32_t time,
uint32_t key,
uint32_t state)
{
/* FALSE means: let the event through to clutter */
return FALSE;
}
static void
modal_modifiers (MetaWaylandKeyboardGrab *grab,
uint32_t serial,
uint32_t mods_depressed,
uint32_t mods_latched,
uint32_t mods_locked,
uint32_t group)
{
}
static MetaWaylandKeyboardGrabInterface modal_grab = {
modal_key,
modal_modifiers,
};
gboolean
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display)
@ -357,8 +318,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
static void
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
{
if (xkb_info->keymap)
xkb_map_unref (xkb_info->keymap);
xkb_keymap_unref (xkb_info->keymap);
xkb_state_unref (xkb_info->state);
if (xkb_info->keymap_area)
munmap (xkb_info->keymap_area, xkb_info->keymap_size);
@ -366,47 +327,7 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
close (xkb_info->keymap_fd);
}
static gboolean
state_equal (MetaWaylandXkbState *one,
MetaWaylandXkbState *two)
{
return one->mods_depressed == two->mods_depressed &&
one->mods_latched == two->mods_latched &&
one->mods_locked == two->mods_locked &&
one->group == two->group;
}
static void
set_modifiers (MetaWaylandKeyboard *keyboard,
guint32 serial,
ClutterEvent *event)
{
MetaWaylandKeyboardGrab *grab = keyboard->grab;
MetaWaylandXkbState new_state;
guint effective_state;
clutter_event_get_state_full (event,
NULL,
&new_state.mods_depressed,
&new_state.mods_latched,
&new_state.mods_locked,
&effective_state);
new_state.group = (effective_state >> 13) & 0x3;
if (state_equal (&keyboard->modifier_state, &new_state))
return;
keyboard->modifier_state = new_state;
grab->interface->modifiers (grab,
serial,
new_state.mods_depressed,
new_state.mods_latched,
new_state.mods_locked,
new_state.group);
}
static gboolean
update_pressed_keys (MetaWaylandKeyboard *keyboard,
uint32_t evdev_code,
gboolean is_press)
@ -417,13 +338,10 @@ update_pressed_keys (MetaWaylandKeyboard *keyboard,
keyboard->keys.size);
uint32_t *k;
/* We want to ignore events that are sent because of auto-repeat. In
the Clutter event stream these appear as a single key press
event. We can detect that because the key will already have been
pressed */
/* Make sure we don't already have this key. */
for (k = keyboard->keys.data; k < end; k++)
if (*k == evdev_code)
return TRUE;
return;
/* Otherwise add the key to the list of pressed keys */
k = wl_array_add (&keyboard->keys, sizeof (*k));
@ -441,18 +359,44 @@ update_pressed_keys (MetaWaylandKeyboard *keyboard,
{
*k = *(end - 1);
keyboard->keys.size -= sizeof (*k);
goto found;
return;
}
g_warning ("unexpected key release event for key 0x%x", evdev_code);
return FALSE;
found:
(void) 0;
}
}
return FALSE;
static guint
evdev_code (const ClutterKeyEvent *event)
{
/* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's
* range, so we do the reverse here. */
return event->hardware_keycode - 8;
}
void
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event)
{
MetaWaylandKeyboardGrab *grab = keyboard->grab;
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
struct xkb_state *state = keyboard->xkb_info.state;
enum xkb_state_component changed_state;
update_pressed_keys (keyboard, evdev_code (event), is_press);
changed_state = xkb_state_update_key (state,
event->hardware_keycode,
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
if (changed_state == 0)
return;
grab->interface->modifiers (grab,
wl_display_next_serial (keyboard->display),
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
}
gboolean
@ -460,34 +404,20 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event)
{
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
guint xkb_keycode, evdev_code;
uint32_t serial;
gboolean autorepeat;
gboolean handled;
xkb_keycode = event->hardware_keycode;
if (event->device == NULL ||
!clutter_input_device_keycode_to_evdev (event->device,
xkb_keycode, &evdev_code))
evdev_code = xkb_keycode - 8; /* What everyone is doing in practice... */
autorepeat = update_pressed_keys (keyboard, evdev_code, is_press);
meta_verbose ("Handling key %s%s event code %d\n",
is_press ? "press" : "release",
autorepeat ? " (autorepeat)" : "",
xkb_keycode);
if (autorepeat)
/* Synthetic key events are for autorepeat. Ignore those, as
* autorepeat in Wayland is done on the client side. */
if (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
return FALSE;
serial = wl_display_next_serial (keyboard->display);
set_modifiers (keyboard, serial, (ClutterEvent*)event);
meta_verbose ("Handling key %s event code %d\n",
is_press ? "press" : "release",
event->hardware_keycode);
handled = keyboard->grab->interface->key (keyboard->grab,
event->time,
evdev_code,
evdev_code (event),
is_press);
if (handled)
@ -535,28 +465,16 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
{
struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
struct wl_display *display = wl_client_get_display (client);
struct xkb_state *state = keyboard->xkb_info.state;
uint32_t serial = wl_display_next_serial (display);
/* If we're in a modal grab, the client is focused but doesn't see
modifiers or pressed keys (and fix that up when we exit the modal) */
if (keyboard->grab->interface == &modal_grab)
{
struct wl_array empty;
wl_array_init (&empty);
wl_keyboard_send_modifiers (keyboard->focus_resource, serial, 0, 0, 0, 0);
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource, &empty);
}
else
{
wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
keyboard->modifier_state.mods_depressed,
keyboard->modifier_state.mods_latched,
keyboard->modifier_state.mods_locked,
keyboard->modifier_state.group);
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
&keyboard->keys);
}
wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
&keyboard->keys);
wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
keyboard->focus_serial = serial;
@ -590,85 +508,6 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
wl_array_release (&keyboard->keys);
}
gboolean
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
guint32 timestamp)
{
MetaWaylandKeyboardGrab *grab;
uint32_t *end = (void *) ((char *) keyboard->keys.data +
keyboard->keys.size);
uint32_t *k;
uint32_t serial;
meta_verbose ("Asked to acquire modal keyboard grab, timestamp %d\n", timestamp);
if (keyboard->grab != &keyboard->default_grab)
return FALSE;
if (keyboard->focus_surface)
{
/* Fake key release events for the focused app */
serial = wl_display_next_serial (keyboard->display);
keyboard->grab->interface->modifiers (keyboard->grab,
serial,
0, 0, 0, 0);
for (k = keyboard->keys.data; k < end; k++)
{
keyboard->grab->interface->key (keyboard->grab,
timestamp,
*k, 0);
}
}
grab = g_slice_new0 (MetaWaylandKeyboardGrab);
grab->interface = &modal_grab;
meta_wayland_keyboard_start_grab (keyboard, grab);
meta_verbose ("Acquired modal keyboard grab, timestamp %d\n", timestamp);
return TRUE;
}
void
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
guint32 timestamp)
{
MetaWaylandKeyboardGrab *grab;
uint32_t *end = (void *) ((char *) keyboard->keys.data +
keyboard->keys.size);
uint32_t *k;
uint32_t serial;
grab = keyboard->grab;
g_assert (grab->interface == &modal_grab);
meta_wayland_keyboard_end_grab (keyboard);
g_slice_free (MetaWaylandKeyboardGrab, grab);
if (keyboard->focus_surface)
{
/* Fake key press events for the focused app */
serial = wl_display_next_serial (keyboard->display);
keyboard->grab->interface->modifiers (keyboard->grab,
serial,
keyboard->modifier_state.mods_depressed,
keyboard->modifier_state.mods_latched,
keyboard->modifier_state.mods_locked,
keyboard->modifier_state.group);
for (k = keyboard->keys.data; k < end; k++)
{
keyboard->grab->interface->key (keyboard->grab,
timestamp,
*k, 1);
}
}
meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
}
void
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
const char *rules,

View File

@ -47,6 +47,7 @@
#include <clutter/clutter.h>
#include <wayland-server.h>
#include <xkbcommon/xkbcommon.h>
struct _MetaWaylandKeyboardGrabInterface
{
@ -68,27 +69,12 @@ struct _MetaWaylandKeyboardGrab
typedef struct
{
struct xkb_keymap *keymap;
struct xkb_state *state;
int keymap_fd;
size_t keymap_size;
char *keymap_area;
xkb_mod_index_t shift_mod;
xkb_mod_index_t caps_mod;
xkb_mod_index_t ctrl_mod;
xkb_mod_index_t alt_mod;
xkb_mod_index_t mod2_mod;
xkb_mod_index_t mod3_mod;
xkb_mod_index_t super_mod;
xkb_mod_index_t mod5_mod;
} MetaWaylandXkbInfo;
typedef struct
{
uint32_t mods_depressed;
uint32_t mods_latched;
uint32_t mods_locked;
uint32_t group;
} MetaWaylandXkbState;
struct _MetaWaylandKeyboard
{
struct wl_list resource_list;
@ -107,8 +93,6 @@ struct _MetaWaylandKeyboard
struct wl_array keys;
MetaWaylandXkbState modifier_state;
struct wl_display *display;
struct xkb_context *xkb_context;
@ -149,14 +133,11 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device,
void
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
gboolean
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
guint32 timestamp);
void
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
guint32 timestamp);
void
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
void
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
const ClutterKeyEvent *event);
#endif /* __META_WAYLAND_KEYBOARD_H__ */

View File

@ -49,7 +49,6 @@
#include "meta-wayland-pointer.h"
#include "meta-wayland-private.h"
#include "xdg-shell-server-protocol.h"
#include <string.h>
@ -60,7 +59,6 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
wl_list_remove (&pointer->focus_surface_listener.link);
pointer->focus_surface = NULL;
if (pointer->focus_resource)
@ -75,14 +73,12 @@ pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
wl_list_remove (&pointer->focus_resource_listener.link);
pointer->focus_resource = NULL;
}
static void
default_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface,
const ClutterEvent *event)
MetaWaylandSurface *surface)
{
MetaWaylandPointer *pointer = grab->pointer;
@ -388,7 +384,7 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
grab->pointer = pointer;
if (pointer->current)
interface->focus (pointer->grab, pointer->current, NULL);
interface->focus (pointer->grab, pointer->current);
}
void
@ -398,62 +394,7 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
pointer->grab = &pointer->default_grab;
interface = pointer->grab->interface;
interface->focus (pointer->grab, pointer->current, NULL);
}
static void
modal_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface,
const ClutterEvent *event)
{
}
static void
modal_motion (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
{
}
static void
modal_button (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
{
}
static MetaWaylandPointerGrabInterface modal_grab = {
modal_focus,
modal_motion,
modal_button
};
gboolean
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
{
MetaWaylandPointerGrab *grab;
if (pointer->grab != &pointer->default_grab)
return FALSE;
meta_wayland_pointer_set_focus (pointer, NULL);
grab = g_slice_new0 (MetaWaylandPointerGrab);
grab->interface = &modal_grab;
meta_wayland_pointer_start_grab (pointer, grab);
return TRUE;
}
void
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer)
{
MetaWaylandPointerGrab *grab;
grab = pointer->grab;
g_assert (grab->interface == &modal_grab);
meta_wayland_pointer_end_grab (pointer);
g_slice_free (MetaWaylandPointerGrab, grab);
interface->focus (pointer->grab, pointer->current);
}
typedef struct {
@ -473,15 +414,14 @@ typedef struct {
static void
popup_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface,
const ClutterEvent *event)
MetaWaylandSurface *surface)
{
MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
/* Popup grabs are in owner-events mode (ie, events for the same client
are reported as normal) */
if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client)
default_grab_focus (grab, surface, event);
default_grab_focus (grab, surface);
else
meta_wayland_pointer_set_focus (grab->pointer, NULL);
}
@ -530,19 +470,18 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link)
{
MetaWaylandSurfaceExtension *xdg_popup = &popup->surface->xdg_popup;
struct wl_client *client = wl_resource_get_client (xdg_popup->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial;
serial = wl_display_next_serial (display);
xdg_popup_send_popup_done (xdg_popup->resource, serial);
meta_wayland_surface_popup_done (popup->surface);
wl_list_remove (&popup->surface_destroy_listener.link);
wl_list_remove (&popup->link);
g_slice_free (MetaWaylandPopup, popup);
}
{
MetaDisplay *display = meta_get_display ();
meta_display_end_grab_op (display,
meta_display_get_current_time_roundtrip (display));
}
meta_wayland_pointer_end_grab (pointer);
g_slice_free (MetaWaylandPopupGrab, popup_grab);
}
@ -582,6 +521,8 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
if (pointer->grab == &pointer->default_grab)
{
MetaWindow *window = surface->window;
grab = g_slice_new0 (MetaWaylandPopupGrab);
grab->generic.interface = &popup_grab_interface;
grab->generic.pointer = pointer;
@ -589,6 +530,19 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
wl_list_init (&grab->all_popups);
meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab);
meta_display_begin_grab_op (window->display,
window->screen,
window,
META_GRAB_OP_WAYLAND_CLIENT,
FALSE, /* pointer_already_grabbed */
FALSE, /* frame_action */
1, /* button. XXX? */
0, /* modmask */
meta_display_get_current_time_roundtrip (window->display),
wl_fixed_to_int (pointer->grab_x),
wl_fixed_to_int (pointer->grab_y));
}
else
grab = (MetaWaylandPopupGrab*)pointer->grab;
@ -597,10 +551,12 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
popup->grab = grab;
popup->surface = surface;
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
if (surface->xdg_popup.resource)
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
else if (surface->wl_shell_surface.resource)
wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
wl_list_insert (&grab->all_popups, &popup->link);
return TRUE;
}
@ -627,3 +583,16 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
*sx = wl_fixed_from_double (xf);
*sy = wl_fixed_from_double (yf);
}
void
meta_wayland_pointer_update_current_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface)
{
pointer->current = surface;
if (surface != pointer->focus_surface)
{
const MetaWaylandPointerGrabInterface *interface =
pointer->grab->interface;
interface->focus (pointer->grab, surface);
}
}

View File

@ -29,8 +29,7 @@
struct _MetaWaylandPointerGrabInterface
{
void (*focus) (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface,
const ClutterEvent *event);
MetaWaylandSurface *surface);
void (*motion) (MetaWaylandPointerGrab *grab,
const ClutterEvent *event);
void (*button) (MetaWaylandPointerGrab *grab,
@ -85,11 +84,6 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
void
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
gboolean
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer);
void
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer);
gboolean
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
MetaWaylandSurface *popup);
@ -100,4 +94,8 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
wl_fixed_t *x,
wl_fixed_t *y);
void
meta_wayland_pointer_update_current_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface);
#endif /* __META_WAYLAND_POINTER_H__ */

View File

@ -21,7 +21,6 @@
#define META_WAYLAND_PRIVATE_H
#include <wayland-server.h>
#include <xkbcommon/xkbcommon.h>
#include <clutter/clutter.h>
#include <glib.h>
@ -31,7 +30,7 @@
#include "meta-weston-launch.h"
#include <meta/meta-cursor-tracker.h>
#include "meta-wayland-types.h"
#include "meta-wayland.h"
#include "meta-wayland-versions.h"
#include "meta-wayland-surface.h"
#include "meta-wayland-seat.h"
@ -91,30 +90,8 @@ struct _MetaWaylandCompositor
MetaWaylandSeat *seat;
};
void meta_wayland_init (void);
void meta_wayland_finalize (void);
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
* API after meta_wayland_init() has been called. */
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
MetaWindow *window);
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event);
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
const ClutterEvent *event);
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
int vt,
GError **error);
#endif /* META_WAYLAND_PRIVATE_H */

View File

@ -276,42 +276,53 @@ static void
handle_scroll_event (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
enum wl_pointer_axis axis;
wl_fixed_t value;
wl_fixed_t x_value = 0, y_value = 0;
notify_motion (seat, event);
if (!seat->pointer.focus_resource)
return;
if (clutter_event_is_pointer_emulated (event))
return;
switch (clutter_event_get_scroll_direction (event))
{
case CLUTTER_SCROLL_UP:
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
value = -DEFAULT_AXIS_STEP_DISTANCE;
y_value = -DEFAULT_AXIS_STEP_DISTANCE;
break;
case CLUTTER_SCROLL_DOWN:
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
value = DEFAULT_AXIS_STEP_DISTANCE;
y_value = DEFAULT_AXIS_STEP_DISTANCE;
break;
case CLUTTER_SCROLL_LEFT:
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
value = -DEFAULT_AXIS_STEP_DISTANCE;
x_value = -DEFAULT_AXIS_STEP_DISTANCE;
break;
case CLUTTER_SCROLL_RIGHT:
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
value = DEFAULT_AXIS_STEP_DISTANCE;
x_value = DEFAULT_AXIS_STEP_DISTANCE;
break;
case CLUTTER_SCROLL_SMOOTH:
{
double dx, dy;
clutter_event_get_scroll_delta (event, &dx, &dy);
x_value = wl_fixed_from_double (dx);
y_value = wl_fixed_from_double (dy);
}
break;
default:
return;
}
if (seat->pointer.focus_resource)
wl_pointer_send_axis (seat->pointer.focus_resource,
clutter_event_get_time (event),
axis,
value);
if (x_value)
wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
if (y_value)
wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
}
static int
@ -336,7 +347,7 @@ count_buttons (const ClutterEvent *event)
return count;
}
void
static void
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
@ -359,6 +370,27 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
}
}
void
meta_wayland_seat_update (MetaWaylandSeat *seat,
const ClutterEvent *event)
{
switch (event->type)
{
case CLUTTER_MOTION:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
meta_wayland_seat_update_pointer (seat, event);
break;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
break;
default:
break;
}
}
gboolean
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
const ClutterEvent *event)
@ -402,6 +434,13 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
ClutterActor *actor = NULL;
MetaWaylandPointer *pointer = &seat->pointer;
MetaWaylandSurface *surface = NULL;
MetaDisplay *display = meta_get_display ();
if (meta_grab_op_is_wayland (display->grab_op))
{
meta_wayland_pointer_update_current_focus (pointer, NULL);
return;
}
if (for_event)
{
@ -424,14 +463,7 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
pointer->current = surface;
if (surface != pointer->focus_surface)
{
const MetaWaylandPointerGrabInterface *interface =
pointer->grab->interface;
interface->focus (pointer->grab,
surface, for_event);
}
meta_wayland_pointer_update_current_focus (pointer, surface);
}
void

View File

@ -43,12 +43,6 @@ struct _MetaWaylandDataSource
{
struct wl_resource *resource;
struct wl_array mime_types;
void (*accept) (MetaWaylandDataSource * source,
uint32_t serial, const char *mime_type);
void (*send) (MetaWaylandDataSource * source,
const char *mime_type, int32_t fd);
void (*cancel) (MetaWaylandDataSource * source);
};
struct _MetaWaylandSeat
@ -77,8 +71,8 @@ MetaWaylandSeat *
meta_wayland_seat_new (struct wl_display *display);
void
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
const ClutterEvent *event);
meta_wayland_seat_update (MetaWaylandSeat *seat,
const ClutterEvent *event);
gboolean
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,

View File

@ -74,17 +74,6 @@ typedef struct
struct wl_listener sibling_destroy_listener;
} MetaWaylandSubsurfacePlacementOp;
static void
surface_handle_buffer_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandSurface *surface = wl_container_of (listener, surface, buffer_destroy_listener);
wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
"Destroyed buffer while it was attached to the surface");
surface->buffer = NULL;
wl_list_remove (&surface->buffer_destroy_listener.link);
}
static void
surface_set_buffer (MetaWaylandSurface *surface,
MetaWaylandBuffer *buffer)
@ -107,6 +96,14 @@ surface_set_buffer (MetaWaylandSurface *surface,
}
}
static void
surface_handle_buffer_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandSurface *surface = wl_container_of (listener, surface, buffer_destroy_listener);
surface_set_buffer (surface, NULL);
}
static void
surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region)
@ -262,9 +259,6 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
CoglError *catch_error = NULL;
CoglTexture *texture;
if (!buffer)
return;
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
buffer->resource,
&catch_error));
@ -295,7 +289,7 @@ actor_surface_commit (MetaWaylandSurface *surface,
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
if (buffer_changed)
if (buffer_changed && buffer)
{
ensure_buffer_texture (buffer);
meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
@ -340,22 +334,6 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
if (pending->frame_extents_changed)
meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
if (pending->maximized.changed)
{
if (pending->maximized.value)
meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
else
meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
}
if (pending->fullscreen.changed)
{
if (pending->fullscreen.value)
meta_window_make_fullscreen (surface->window);
else
meta_window_unmake_fullscreen (surface->window);
}
}
static void
@ -381,8 +359,6 @@ double_buffered_state_init (MetaWaylandDoubleBufferedState *state)
wl_list_init (&state->frame_callback_list);
state->frame_extents_changed = FALSE;
state->maximized.changed = FALSE;
state->fullscreen.changed = FALSE;
}
static void
@ -650,18 +626,9 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
static void
destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
{
wl_list_remove (&extension->surface_destroy_listener.link);
extension->resource = NULL;
}
static void
extension_handle_surface_destroy (struct wl_listener *listener,
void *data)
{
MetaWaylandSurfaceExtension *extension = wl_container_of (listener, extension, surface_destroy_listener);
wl_resource_destroy (extension->resource);
}
static int
get_resource_version (struct wl_resource *master_resource,
int max_version)
@ -671,23 +638,22 @@ get_resource_version (struct wl_resource *master_resource,
static gboolean
create_surface_extension (MetaWaylandSurfaceExtension *extension,
struct wl_client *client,
struct wl_resource *master_resource,
struct wl_resource *surface_resource,
guint32 id,
int max_version,
const struct wl_interface *interface,
const void *implementation,
wl_resource_destroy_func_t destructor)
wl_resource_destroy_func_t destructor,
MetaWaylandSurface *surface,
struct wl_resource *master_resource,
guint32 id)
{
struct wl_client *client;
if (extension->resource != NULL)
return FALSE;
client = wl_resource_get_client (surface->resource);
extension->resource = wl_resource_create (client, interface, get_resource_version (master_resource, max_version), id);
wl_resource_set_implementation (extension->resource, implementation, extension, destructor);
extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
wl_resource_add_destroy_listener (surface_resource, &extension->surface_destroy_listener);
wl_resource_set_implementation (extension->resource, implementation, surface, destructor);
return TRUE;
}
@ -714,11 +680,10 @@ xdg_shell_pong (struct wl_client *client,
static void
xdg_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_window (surface);
destroy_surface_extension (xdg_surface);
destroy_surface_extension (&surface->xdg_surface);
}
static void
@ -733,8 +698,7 @@ xdg_surface_set_transient_for (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *parent_resource)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWindow *transient_for = NULL;
if (parent_resource)
@ -754,8 +718,7 @@ xdg_surface_set_margin (struct wl_client *client,
int32_t top_margin,
int32_t bottom_margin)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->pending.frame_extents_changed = TRUE;
surface->pending.frame_extents.left = left_margin;
@ -769,8 +732,7 @@ xdg_surface_set_title (struct wl_client *client,
struct wl_resource *resource,
const char *title)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
meta_window_set_title (surface->window, title);
}
@ -780,8 +742,7 @@ xdg_surface_set_app_id (struct wl_client *client,
struct wl_resource *resource,
const char *app_id)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
meta_window_set_wm_class (surface->window, app_id, app_id);
}
@ -816,8 +777,7 @@ xdg_surface_move (struct wl_client *client,
guint32 serial)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial ||
@ -828,7 +788,7 @@ xdg_surface_move (struct wl_client *client,
}
static MetaGrabOp
grab_op_for_edge (int edge)
grab_op_for_xdg_surface_resize_edge (int edge)
{
switch (edge)
{
@ -862,15 +822,14 @@ xdg_surface_resize (struct wl_client *client,
guint32 edges)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial ||
seat->pointer.focus_surface != surface)
return;
begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));
begin_grab_op_on_surface (surface, seat, grab_op_for_xdg_surface_resize_edge (edges));
}
static void
@ -882,55 +841,51 @@ xdg_surface_set_output (struct wl_client *client,
}
static void
xdg_surface_set_fullscreen (struct wl_client *client,
struct wl_resource *resource)
xdg_surface_request_change_state (struct wl_client *client,
struct wl_resource *resource,
uint32_t state_type,
uint32_t value,
uint32_t serial)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->pending.fullscreen.changed = TRUE;
surface->pending.fullscreen.value = TRUE;
surface->state_changed_serial = serial;
switch (state_type)
{
case XDG_SURFACE_STATE_MAXIMIZED:
if (value)
meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
else
meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
break;
case XDG_SURFACE_STATE_FULLSCREEN:
if (value)
meta_window_make_fullscreen (surface->window);
else
meta_window_unmake_fullscreen (surface->window);
}
}
static void
xdg_surface_unset_fullscreen (struct wl_client *client,
struct wl_resource *resource)
xdg_surface_ack_change_state (struct wl_client *client,
struct wl_resource *resource,
uint32_t state_type,
uint32_t value,
uint32_t serial)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
surface->pending.fullscreen.changed = TRUE;
surface->pending.fullscreen.value = FALSE;
}
static void
xdg_surface_set_maximized (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
surface->pending.maximized.changed = TRUE;
surface->pending.maximized.value = TRUE;
}
static void
xdg_surface_unset_maximized (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
surface->pending.maximized.changed = TRUE;
surface->pending.maximized.value = FALSE;
/* Do nothing for now. In the future, we'd imagine that
* we'd ignore attaches when we have a state pending that
* we haven't had the client ACK'd, to prevent a race
* condition when we have an in-flight attach when the
* client gets the new state. */
}
static void
xdg_surface_set_minimized (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
meta_window_minimize (surface->window);
}
@ -944,10 +899,8 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
xdg_surface_move,
xdg_surface_resize,
xdg_surface_set_output,
xdg_surface_set_fullscreen,
xdg_surface_unset_fullscreen,
xdg_surface_set_maximized,
xdg_surface_unset_maximized,
xdg_surface_request_change_state,
xdg_surface_ack_change_state,
xdg_surface_set_minimized,
};
@ -959,11 +912,12 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
if (!create_surface_extension (&surface->xdg_surface, client, surface_resource, resource, id,
if (!create_surface_extension (&surface->xdg_surface,
META_XDG_SURFACE_VERSION,
&xdg_surface_interface,
&meta_wayland_xdg_surface_interface,
xdg_surface_destructor))
xdg_surface_destructor,
surface, resource, id))
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -978,11 +932,10 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
static void
xdg_popup_destructor (struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_window (surface);
destroy_surface_extension (xdg_popup);
destroy_surface_extension (&surface->xdg_popup);
}
static void
@ -1015,11 +968,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
if (parent_surf == NULL || parent_surf->window == NULL)
return;
if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id,
if (!create_surface_extension (&surface->xdg_popup,
META_XDG_POPUP_VERSION,
&xdg_popup_interface,
&meta_wayland_xdg_popup_interface,
xdg_popup_destructor))
xdg_popup_destructor,
surface, resource, id))
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1035,8 +989,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
surface->window->placed = TRUE;
meta_window_set_transient_for (surface->window, parent_surf->window);
surface->window->type = META_WINDOW_DROPDOWN_MENU;
meta_window_type_changed (surface->window);
meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
@ -1102,13 +1055,264 @@ bind_xdg_shell (struct wl_client *client,
wl_client_add_destroy_listener (client, &xdg_shell->client_destroy_listener);
}
static void
wl_shell_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_surface_extension (&surface->wl_shell_surface);
}
static void
wl_shell_surface_pong (struct wl_client *client,
struct wl_resource *resource,
uint32_t serial)
{
MetaDisplay *display = meta_get_display ();
meta_display_pong_for_serial (display, serial);
}
static void
wl_shell_surface_move (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *seat_resource,
uint32_t serial)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial ||
seat->pointer.focus_surface != surface)
return;
begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING);
}
static MetaGrabOp
grab_op_for_wl_shell_surface_resize_edge (int edge)
{
switch (edge)
{
case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
return META_GRAB_OP_RESIZING_NW;
case WL_SHELL_SURFACE_RESIZE_TOP:
return META_GRAB_OP_RESIZING_N;
case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
return META_GRAB_OP_RESIZING_NE;
case WL_SHELL_SURFACE_RESIZE_RIGHT:
return META_GRAB_OP_RESIZING_E;
case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
return META_GRAB_OP_RESIZING_SE;
case WL_SHELL_SURFACE_RESIZE_BOTTOM:
return META_GRAB_OP_RESIZING_S;
case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
return META_GRAB_OP_RESIZING_SW;
case WL_SHELL_SURFACE_RESIZE_LEFT:
return META_GRAB_OP_RESIZING_W;
default:
g_warning ("invalid edge: %d", edge);
return META_GRAB_OP_NONE;
}
}
static void
wl_shell_surface_resize (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *seat_resource,
uint32_t serial,
uint32_t edges)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (seat->pointer.button_count == 0 ||
seat->pointer.grab_serial != serial ||
seat->pointer.focus_surface != surface)
return;
begin_grab_op_on_surface (surface, seat, grab_op_for_wl_shell_surface_resize_edge (edges));
}
typedef enum {
SURFACE_STATE_TOPLEVEL,
SURFACE_STATE_FULLSCREEN,
SURFACE_STATE_MAXIMIZED,
} SurfaceState;
static void
wl_shell_surface_set_state (MetaWaylandSurface *surface,
SurfaceState state)
{
if (state == SURFACE_STATE_FULLSCREEN)
meta_window_make_fullscreen (surface->window);
else
meta_window_unmake_fullscreen (surface->window);
if (state == SURFACE_STATE_MAXIMIZED)
meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
else
meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
}
static void
wl_shell_surface_set_toplevel (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
}
static void
wl_shell_surface_set_transient (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *parent_resource,
int32_t x,
int32_t y,
uint32_t flags)
{
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_window_move (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
}
static void
wl_shell_surface_set_fullscreen (struct wl_client *client,
struct wl_resource *resource,
uint32_t method,
uint32_t framerate,
struct wl_resource *output)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
wl_shell_surface_set_state (surface, SURFACE_STATE_FULLSCREEN);
}
static void
wl_shell_surface_set_popup (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *seat_resource,
uint32_t serial,
struct wl_resource *parent_resource,
int32_t x,
int32_t y,
uint32_t flags)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_window_move (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
static void
wl_shell_surface_set_maximized (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *output)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
wl_shell_surface_set_state (surface, SURFACE_STATE_MAXIMIZED);
}
static void
wl_shell_surface_set_title (struct wl_client *client,
struct wl_resource *resource,
const char *title)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
meta_window_set_title (surface->window, title);
}
static void
wl_shell_surface_set_class (struct wl_client *client,
struct wl_resource *resource,
const char *class_)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
meta_window_set_wm_class (surface->window, class_, class_);
}
static const struct wl_shell_surface_interface meta_wayland_wl_shell_surface_interface = {
wl_shell_surface_pong,
wl_shell_surface_move,
wl_shell_surface_resize,
wl_shell_surface_set_toplevel,
wl_shell_surface_set_transient,
wl_shell_surface_set_fullscreen,
wl_shell_surface_set_popup,
wl_shell_surface_set_maximized,
wl_shell_surface_set_title,
wl_shell_surface_set_class,
};
static void
wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
if (!create_surface_extension (&surface->wl_shell_surface,
META_WL_SHELL_SURFACE_VERSION,
&wl_shell_surface_interface,
&meta_wayland_wl_shell_surface_interface,
wl_shell_surface_destructor,
surface, resource, id))
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"wl_shell::get_shell_surface already requested");
return;
}
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
}
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
wl_shell_get_shell_surface,
};
static void
bind_wl_shell (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create (client, &wl_shell_interface,
MIN (META_WL_SHELL_VERSION, version), id);
wl_resource_set_implementation (resource, &meta_wayland_wl_shell_interface, data, NULL);
}
static void
gtk_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
destroy_surface_extension (gtk_surface);
destroy_surface_extension (&surface->gtk_surface);
}
static void
@ -1121,8 +1325,7 @@ set_dbus_properties (struct wl_client *client,
const char *application_object_path,
const char *unique_bus_name)
{
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
/* Broken client, let it die instead of us */
if (!surface->window)
@ -1152,11 +1355,12 @@ get_gtk_surface (struct wl_client *client,
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
if (!create_surface_extension (&surface->gtk_surface, client, surface_resource, resource, id,
if (!create_surface_extension (&surface->gtk_surface,
META_GTK_SURFACE_VERSION,
&gtk_surface_interface,
&meta_wayland_gtk_surface_interface,
gtk_surface_destructor))
gtk_surface_destructor,
surface, resource, id))
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1238,8 +1442,6 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface)
if (surface->sub.synchronous)
commit_double_buffered_state (surface, pending_surface_state);
double_buffered_state_reset (pending_surface_state);
}
static void
@ -1253,8 +1455,7 @@ unparent_actor (MetaWaylandSurface *surface)
static void
wl_subsurface_destructor (struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (surface->sub.parent)
{
@ -1266,7 +1467,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
}
double_buffered_state_destroy (&surface->sub.pending_surface_state);
destroy_surface_extension (subsurface);
destroy_surface_extension (&surface->subsurface);
}
static void
@ -1282,8 +1483,7 @@ wl_subsurface_set_position (struct wl_client *client,
int32_t x,
int32_t y)
{
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->sub.pending_x = x;
surface->sub.pending_y = y;
@ -1333,8 +1533,7 @@ wl_subsurface_place_above (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *sibling_resource)
{
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
if (!is_valid_sibling (surface, sibling))
@ -1356,8 +1555,7 @@ wl_subsurface_place_below (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *sibling_resource)
{
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
if (!is_valid_sibling (surface, sibling))
@ -1378,10 +1576,7 @@ static void
wl_subsurface_set_sync (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *subsurface =
wl_resource_get_user_data (resource);
MetaWaylandSurface *surface =
wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->sub.synchronous = TRUE;
}
@ -1390,10 +1585,7 @@ static void
wl_subsurface_set_desync (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurfaceExtension *subsurface =
wl_resource_get_user_data (resource);
MetaWaylandSurface *surface =
wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
if (surface->sub.synchronous)
subsurface_parent_surface_committed (surface);
@ -1439,11 +1631,12 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id,
if (!create_surface_extension (&surface->subsurface,
META_GTK_SURFACE_VERSION,
&wl_subsurface_interface,
&meta_wayland_subsurface_interface,
wl_subsurface_destructor))
wl_subsurface_destructor,
surface, resource, id))
{
wl_resource_post_error (surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -1489,6 +1682,11 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor)
compositor, bind_xdg_shell) == NULL)
g_error ("Failed to register a global xdg-shell object");
if (wl_global_create (compositor->wayland_display,
&wl_shell_interface, 1,
compositor, bind_wl_shell) == NULL)
g_error ("Failed to register a global wl-shell object");
if (wl_global_create (compositor->wayland_display,
&gtk_shell_interface,
META_GTK_SHELL_VERSION,
@ -1510,6 +1708,58 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
if (surface->xdg_surface.resource)
xdg_surface_send_configure (surface->xdg_surface.resource,
new_width, new_height);
else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
0, new_width, new_height);
}
static void
send_change_state (MetaWaylandSurface *surface,
uint32_t state_type,
uint32_t value)
{
if (surface->xdg_surface.resource)
{
uint32_t serial;
if (surface->state_changed_serial != 0)
{
serial = surface->state_changed_serial;
surface->state_changed_serial = 0;
}
else
{
struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
struct wl_display *display = wl_client_get_display (client);
serial = wl_display_next_serial (display);
}
xdg_surface_send_change_state (surface->xdg_surface.resource, state_type, value, serial);
}
}
void
meta_wayland_surface_send_maximized (MetaWaylandSurface *surface)
{
send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, TRUE);
}
void
meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface)
{
send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, FALSE);
}
void
meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface)
{
send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, TRUE);
}
void
meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface)
{
send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, FALSE);
}
void
@ -1530,16 +1780,23 @@ void
meta_wayland_surface_ping (MetaWaylandSurface *surface,
guint32 serial)
{
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
if (xdg_shell == NULL)
if (surface->xdg_surface.resource)
{
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
return;
}
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
xdg_shell_send_ping (xdg_shell, serial);
if (xdg_shell == NULL)
{
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
return;
}
xdg_shell_send_ping (xdg_shell, serial);
}
else if (surface->wl_shell_surface.resource)
{
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
}
}
void
@ -1548,3 +1805,16 @@ meta_wayland_surface_delete (MetaWaylandSurface *surface)
if (surface->xdg_surface.resource)
xdg_surface_send_delete (surface->xdg_surface.resource);
}
void
meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
{
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
if (surface->xdg_popup.resource)
xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
else if (surface->wl_shell_surface.resource)
wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
}

View File

@ -41,12 +41,6 @@ struct _MetaWaylandBuffer
uint32_t ref_count;
};
typedef struct
{
guint changed : 1;
guint value : 1;
} MetaWaylandStateFlag;
typedef struct
{
/* wl_surface.attach */
@ -67,15 +61,11 @@ typedef struct
gboolean frame_extents_changed;
GtkBorder frame_extents;
MetaWaylandStateFlag fullscreen;
MetaWaylandStateFlag maximized;
} MetaWaylandDoubleBufferedState;
typedef struct
{
struct wl_resource *resource;
struct wl_listener surface_destroy_listener;
} MetaWaylandSurfaceExtension;
struct _MetaWaylandSurface
@ -86,6 +76,7 @@ struct _MetaWaylandSurface
MetaWindow *window;
MetaWaylandSurfaceExtension xdg_surface;
MetaWaylandSurfaceExtension xdg_popup;
MetaWaylandSurfaceExtension wl_shell_surface;
MetaWaylandSurfaceExtension gtk_surface;
MetaWaylandSurfaceExtension subsurface;
@ -107,6 +98,8 @@ struct _MetaWaylandSurface
GSList *pending_placement_ops;
} sub;
uint32_t state_changed_serial;
/* All the pending state, that wl_surface.commit will apply. */
MetaWaylandDoubleBufferedState pending;
};
@ -124,6 +117,10 @@ void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *s
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width,
int height);
void meta_wayland_surface_send_maximized (MetaWaylandSurface *surface);
void meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface);
void meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface);
void meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface);
void meta_wayland_surface_activated (MetaWaylandSurface *surface);
void meta_wayland_surface_deactivated (MetaWaylandSurface *surface);
@ -132,4 +129,7 @@ void meta_wayland_surface_ping (MetaWaylandSurface *surface,
guint32 serial);
void meta_wayland_surface_delete (MetaWaylandSurface *surface);
void meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
#endif

View File

@ -37,6 +37,7 @@
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
#define META_WL_COMPOSITOR_VERSION 3
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
#define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_VERSION 1
@ -52,9 +53,10 @@
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */
#define META_WL_SHELL_SURFACE_VERSION 1 /* from wl_shell */
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
#define META_WL_SUBSURFACE_VERSION 1 /* from wl_subcompositor */
/* The first version to implement a specific event */

View File

@ -151,7 +151,6 @@ meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
if (buffer->ref_count == 0)
{
g_clear_pointer (&buffer->texture, cogl_object_unref);
g_assert (wl_resource_get_client (buffer->resource));
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
}
}
@ -508,6 +507,15 @@ stage_destroy_cb (void)
meta_quit (META_EXIT_SUCCESS);
}
/**
* meta_wayland_compositor_update:
* @compositor: the #MetaWaylandCompositor instance
* @event: the #ClutterEvent used to update @seat's state
*
* This is used to update display server state like updating cursor
* position and keeping track of buttons and keys pressed. It must be
* called for all input events coming from the underlying devices.
*/
void
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
@ -536,18 +544,18 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
meta_idle_monitor_reset_idletime (device_monitor);
}
switch (event->type)
{
case CLUTTER_MOTION:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_SCROLL:
meta_wayland_seat_update_pointer (compositor->seat, event);
default:
break;
}
meta_wayland_seat_update (compositor->seat, event);
}
/**
* meta_wayland_compositor_handle_event:
* @compositor: the #MetaWaylandCompositor instance
* @event: the #ClutterEvent to be sent
*
* This method sends events to the focused wayland client, if any.
*
* Return value: whether @event was sent to a wayland client.
*/
gboolean
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
@ -643,6 +651,8 @@ meta_wayland_init (void)
clutter_wayland_set_compositor_display (compositor->wayland_display);
/* If we're running on bare metal, we're a display server,
* so start talking to weston-launch. */
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
compositor->launcher = meta_launcher_new ();
@ -651,17 +661,6 @@ meta_wayland_init (void)
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Failed to initialize Clutter");
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *cogl_context = clutter_backend_get_cogl_context (backend);
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
int drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
meta_launcher_set_drm_fd (compositor->launcher, drm_fd, NULL);
}
#endif
meta_monitor_manager_initialize ();
monitors = meta_monitor_manager_get ();
g_signal_connect (monitors, "monitors-changed",
@ -728,7 +727,22 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
}
else
{
g_debug ("Ignoring VT switch keybinding, not running as VT manager");
g_debug ("Ignoring VT switch keybinding, not running as display server");
return TRUE;
}
}
gboolean
meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
GError **error)
{
if (compositor->launcher)
{
return meta_launcher_activate_vt (compositor->launcher, -1, error);
}
else
{
g_debug ("Ignoring activate_session, not running as display server");
return TRUE;
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2014 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_WAYLAND_H
#define META_WAYLAND_H
#include "meta-wayland-types.h"
void meta_wayland_init (void);
void meta_wayland_finalize (void);
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
* API after meta_wayland_init() has been called. */
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
MetaWindow *window);
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
const ClutterEvent *event);
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
const ClutterEvent *event);
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
int vt,
GError **error);
gboolean meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
GError **error);
#endif

View File

@ -23,6 +23,7 @@
#include <gio/gunixfdmessage.h>
#include <clutter/clutter.h>
#include <clutter/egl/clutter-egl.h>
#include <clutter/evdev/clutter-evdev.h>
#include <glib.h>
@ -41,6 +42,8 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include "meta-weston-launch.h"
struct _MetaLauncher
@ -154,36 +157,11 @@ send_message_to_wl (MetaLauncher *self,
return TRUE;
}
gboolean
meta_launcher_set_drm_fd (MetaLauncher *self,
int drm_fd,
GError **error)
{
struct weston_launcher_message message;
GSocketControlMessage *cmsg;
gboolean ok;
message.opcode = WESTON_LAUNCHER_DRM_SET_FD;
cmsg = g_unix_fd_message_new ();
if (g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (cmsg),
drm_fd, error) == FALSE)
{
g_object_unref (cmsg);
return FALSE;
}
ok = send_message_to_wl (self, &message, sizeof message, cmsg, NULL, error);
g_object_unref (cmsg);
return ok;
}
int
meta_launcher_open_input_device (MetaLauncher *self,
const char *name,
int flags,
GError **error)
static int
meta_launcher_open_device (MetaLauncher *self,
const char *name,
int flags,
GError **error)
{
struct weston_launcher_open *message;
GSocketControlMessage *cmsg;
@ -232,6 +210,17 @@ meta_launcher_enter (MetaLauncher *launcher)
cogl_kms_display_queue_modes_reset (cogl_display);
clutter_evdev_reclaim_devices ();
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
/* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to
* update. */
clutter_actor_queue_redraw (compositor->stage);
meta_cursor_tracker_force_update (compositor->seat->cursor_tracker);
}
}
static void
@ -248,7 +237,14 @@ on_evdev_device_open (const char *path,
{
MetaLauncher *launcher = user_data;
return meta_launcher_open_input_device (launcher, path, flags, error);
return meta_launcher_open_device (launcher, path, flags, error);
}
static void
on_evdev_device_close (int fd,
gpointer user_data)
{
close (fd);
}
static void
@ -354,8 +350,6 @@ meta_launcher_new (void)
self->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
clutter_evdev_set_open_callback (on_evdev_device_open, self);
self->nested_context = g_main_context_new ();
self->nested_loop = g_main_loop_new (self->nested_context, FALSE);
@ -369,6 +363,22 @@ meta_launcher_new (void)
g_source_attach (self->inner_source, self->nested_context);
g_source_unref (self->inner_source);
clutter_evdev_set_device_callbacks (on_evdev_device_open,
on_evdev_device_close,
self);
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
GError *error = NULL;
int fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
if (error)
g_error ("Failed to open /dev/dri/card0: %s", error->message);
clutter_egl_set_kms_fd (fd);
}
#endif
return self;
}
@ -388,7 +398,7 @@ meta_launcher_free (MetaLauncher *launcher)
gboolean
meta_launcher_activate_vt (MetaLauncher *launcher,
int vt,
signed char vt,
GError **error)
{
struct weston_launcher_activate_vt message;

View File

@ -29,18 +29,6 @@ MetaLauncher *meta_launcher_new (void);
void meta_launcher_free (MetaLauncher *self);
gboolean meta_launcher_activate_vt (MetaLauncher *self,
int number,
signed char vt,
GError **error);
gboolean meta_launcher_set_drm_fd (MetaLauncher *self,
int drm_fd,
GError **error);
gboolean meta_launcher_set_master (MetaLauncher *self,
gboolean master,
GError **error);
int meta_launcher_open_input_device (MetaLauncher *self,
const char *name,
int flags,
GError **error);
#endif

View File

@ -47,10 +47,19 @@ xserver_set_window_id (struct wl_client *client,
if (!window)
return;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_make_toplevel (surface);
surface->window = window;
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
}
static const struct xserver_interface xserver_implementation = {
@ -294,9 +303,6 @@ meta_xwayland_start (MetaXWaylandManager *manager,
pid_t pid;
char **env;
char *fd_string;
char *log_path;
char *args[10];
GError *error;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
@ -355,47 +361,43 @@ meta_xwayland_start (MetaXWaylandManager *manager,
g_free (fd_string);
manager->display_name = g_strdup_printf (":%d", manager->display_index);
log_path = g_build_filename (g_get_user_cache_dir (), "xwayland.log", NULL);
args[0] = XWAYLAND_PATH;
args[1] = manager->display_name;
args[2] = "-wayland";
args[3] = "-rootless";
args[4] = "-noreset";
args[5] = "-logfile";
args[6] = log_path;
args[7] = "-nolisten";
args[8] = "all";
args[9] = NULL;
{
GError *error = NULL;
gchar *args[] = { XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten",
"all",
NULL };
error = NULL;
if (g_spawn_async (NULL, /* cwd */
args,
env,
G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
G_SPAWN_DO_NOT_REAP_CHILD |
G_SPAWN_STDOUT_TO_DEV_NULL |
G_SPAWN_STDERR_TO_DEV_NULL,
uncloexec,
GINT_TO_POINTER (sp[1]),
&pid,
&error))
{
g_message ("forked X server, pid %d\n", pid);
if (g_spawn_async (NULL, /* cwd */
args,
env,
G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
G_SPAWN_DO_NOT_REAP_CHILD,
uncloexec,
GINT_TO_POINTER (sp[1]),
&pid,
&error))
{
g_message ("forked X server, pid %d\n", pid);
close (sp[1]);
manager->client = wl_client_create (wl_display, sp[0]);
close (sp[1]);
manager->client = wl_client_create (wl_display, sp[0]);
manager->pid = pid;
g_child_watch_add (pid, xserver_died, NULL);
}
else
{
g_error ("Failed to fork for xwayland server: %s", error->message);
}
manager->pid = pid;
g_child_watch_add (pid, xserver_died, NULL);
}
else
{
g_error ("Failed to fork for xwayland server: %s", error->message);
}
}
g_strfreev (env);
g_free (log_path);
/* We need to run a mainloop until we know xwayland has a binding
* for our xserver interface at which point we can assume it's

View File

@ -40,19 +40,22 @@
<enum name="version">
<description summary="latest protocol version">
Use this enum to check the protocol version, and it will be updated
automatically.
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="2" summary="Always the latest version"/>
<entry name="current" value="3" summary="Always the latest version"/>
</enum>
<request name="use_unstable_version">
<description summary="enable use of this unstable version">
Use this request in order to enable use of this interface.
Understand and agree that one is using an unstable interface,
that will likely change in the future, breaking the API.
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>
@ -275,113 +278,87 @@
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
</request>
<event name="request_set_fullscreen">
<description summary="server requests that the client set fullscreen">
Event sent from the compositor to the client requesting that the client
goes to a fullscreen state. It's the client job to call set_fullscreen
and really trigger the fullscreen state.
<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>
</event>
<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>
<event name="request_unset_fullscreen">
<description summary="server requests that the client unset fullscreen">
Event sent from the compositor to the client requesting that the client
leaves the fullscreen state. It's the client job to call
unset_fullscreen and really leave the fullscreen state.
</description>
</event>
<request name="set_fullscreen">
<description summary="set the surface state as fullscreen">
Set the surface as fullscreen.
After this request, the compositor should send a configure event
informing the output size.
This request informs the compositor that the next attached buffer
committed will be in a fullscreen state. The buffer size should be the
same size as the size informed in the configure event, if the client
doesn't want to leave any empty area.
In other words: the next attached buffer after set_maximized is the new
maximized buffer. And the surface will be positioned at the maximized
position on commit.
A simple way to synchronize and wait for the correct configure event is
to use a wl_display.sync request right after the set_fullscreen
request. When the sync callback returns, the last configure event
received just before it will be the correct one, and should contain the
right size for the surface to maximize.
Setting one state won't unset another state. Use
xdg_surface.unset_fullscreen for unsetting it.
<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>
<request name="unset_fullscreen">
<description summary="unset the surface state as fullscreen">
Unset the surface fullscreen state.
Same negotiation as set_fullscreen must be used.
<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>
</request>
<event name="request_set_maximized">
<description summary="server requests that the client set maximized">
Event sent from the compositor to the client requesting that the client
goes to a maximized state. It's the client job to call set_maximized
and really trigger the maximized 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="a serial for the compositor's own tracking"/>
</event>
<event name="request_unset_maximized">
<description summary="server requests that the client unset maximized">
Event sent from the compositor to the client requesting that the client
leaves the maximized state. It's the client job to call unset_maximized
and really leave the maximized state.
</description>
</event>
<request name="set_maximized">
<description summary="set the surface state as maximized">
Set the surface as maximized.
After this request, the compositor will send a configure event
informing the output size minus panel and other MW decorations.
This request informs the compositor that the next attached buffer
committed will be in a maximized state. The buffer size should be the
same size as the size informed in the configure event, if the client
doesn't want to leave any empty area.
In other words: the next attached buffer after set_maximized is the new
maximized buffer. And the surface will be positioned at the maximized
position on commit.
A simple way to synchronize and wait for the correct configure event is
to use a wl_display.sync request right after the set_maximized request.
When the sync callback returns, the last configure event received just
before it will be the correct one, and should contain the right size
for the surface to maximize.
Setting one state won't unset another state. Use
xdg_surface.unset_maximized for unsetting it.
</description>
</request>
<request name="unset_maximized">
<description summary="unset the surface state as maximized">
Unset the surface maximized state.
Same negotiation as set_maximized must be used.
<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="set the surface state as minimized">
Set the surface minimized state.
Setting one state won't unset another state.
<description summary="minimize the surface">
Minimize the surface.
</description>
</request>

View File

@ -80,6 +80,7 @@ struct weston_launch {
struct termios terminal_attributes;
int kb_mode;
enum vt_state vt_state;
unsigned vt;
int drm_fd;
};
@ -164,69 +165,6 @@ setenv_fd(const char *env, int fd)
setenv(env, buf, 1);
}
static int
handle_setdrmfd(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
struct weston_launcher_reply reply;
struct cmsghdr *cmsg;
union cmsg_data *data;
struct stat s;
reply.header.opcode = WESTON_LAUNCHER_DRM_SET_FD;
reply.ret = -1;
if (wl->drm_fd != -1) {
error(0, 0, "DRM FD already set");
reply.ret = -EINVAL;
goto out;
}
cmsg = CMSG_FIRSTHDR(msg);
if (!cmsg ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
error(0, 0, "invalid control message");
reply.ret = -EINVAL;
goto out;
}
data = (union cmsg_data *) CMSG_DATA(cmsg);
if (data->fd < 0) {
error(0, 0, "missing drm fd in socket request");
reply.ret = -EINVAL;
goto out;
}
if (fstat(data->fd, &s) < 0) {
reply.ret = -errno;
goto out;
}
if (major(s.st_rdev) != DRM_MAJOR) {
fprintf(stderr, "FD is not for DRM\n");
reply.ret = -EPERM;
goto out;
}
wl->drm_fd = data->fd;
reply.ret = drmSetMaster(data->fd);
if (reply.ret < 0)
reply.ret = -errno;
if (wl->verbose)
fprintf(stderr, "mutter-launch: set drm FD, ret: %d, fd: %d\n",
reply.ret, data->fd);
out:
do {
len = send(wl->sock[0], &reply, sizeof reply, 0);
} while (len < 0 && errno == EINTR);
if (len < 0)
return -1;
return 0;
}
static int
handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
@ -274,6 +212,7 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
struct weston_launcher_reply reply;
struct weston_launcher_activate_vt *message;
unsigned vt;
reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
reply.ret = -1;
@ -285,7 +224,13 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
message = msg->msg_iov->iov_base;
reply.ret = ioctl(wl->tty, VT_ACTIVATE, message->vt);
/* Negative values mean that we're activating our own VT */
if (message->vt > 0)
vt = message->vt;
else
vt = wl->vt;
reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt);
if (reply.ret < 0)
reply.ret = -errno;
@ -315,6 +260,7 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
struct iovec iov;
struct weston_launcher_open *message;
union cmsg_data *data;
int dev_major;
reply.header.opcode = WESTON_LAUNCHER_OPEN;
reply.ret = -1;
@ -331,6 +277,22 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
goto err0;
}
dev_major = major(s.st_rdev);
if (dev_major != INPUT_MAJOR &&
dev_major != DRM_MAJOR) {
fprintf(stderr, "Device %s is not an input or DRM device\n",
message->path);
reply.ret = -EPERM;
goto err0;
}
if (dev_major == DRM_MAJOR && wl->drm_fd != -1) {
fprintf(stderr, "Already have a DRM device open\n");
reply.ret = -EPERM;
goto err0;
}
fd = open(message->path, message->flags);
if (fd < 0) {
fprintf(stderr, "Error opening device %s: %m\n",
@ -339,13 +301,8 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
goto err0;
}
if (major(s.st_rdev) != INPUT_MAJOR) {
close(fd);
fd = -1;
fprintf(stderr, "Device %s is not an input device\n",
message->path);
reply.ret = -EPERM;
goto err0;
if (dev_major == DRM_MAJOR) {
wl->drm_fd = fd;
}
err0:
@ -413,9 +370,6 @@ handle_socket_msg(struct weston_launch *wl)
case WESTON_LAUNCHER_OPEN:
ret = handle_open(wl, &msg, len);
break;
case WESTON_LAUNCHER_DRM_SET_FD:
ret = handle_setdrmfd(wl, &msg, len);
break;
case WESTON_LAUNCHER_CONFIRM_VT_SWITCH:
ret = handle_confirm_vt_switch(wl, &msg, len);
break;
@ -554,7 +508,7 @@ setup_tty(struct weston_launch *wl)
struct stat buf;
struct termios raw_attributes;
struct vt_mode mode = { 0 };
char *session, *tty;
char *session;
char path[PATH_MAX];
int ok;
@ -562,44 +516,13 @@ setup_tty(struct weston_launch *wl)
if (ok < 0)
error(1, -ok, "could not determine current session");
ok = sd_session_get_tty(session, &tty);
if (ok == 0) {
/* Old systemd only has the tty name in the TTY
field, new one has the full char device path.
Check what we have and fix it properly.
*/
if (strncmp(tty, "/dev", strlen("/dev")) == 0) {
strncpy(path, tty, PATH_MAX);
path[PATH_MAX-1] = 0;
} else {
snprintf(path, PATH_MAX, "/dev/%s", tty);
}
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
free(tty);
#ifdef HAVE_SD_SESSION_GET_VT
} else if (ok == -ENOENT) {
unsigned vt;
/* Negative errnos are cool, right?
So cool that we can't distinguish "session not found"
from "key does not exist in the session file"!
Let's assume the latter, as we got the value
from sd_pid_get_session()...
*/
ok = sd_session_get_vt(session, &vt);
if (ok < 0)
error(1, -ok, "could not determine current TTY");
snprintf(path, PATH_MAX, "/dev/tty%u", vt);
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
free(tty);
#endif
} else
ok = sd_session_get_vt(session, &wl->vt);
if (ok < 0)
error(1, -ok, "could not determine current TTY");
snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
if (wl->tty < 0)
error(1, errno, "failed to open tty");

View File

@ -31,9 +31,8 @@ enum weston_launcher_message_type {
enum weston_launcher_opcode {
WESTON_LAUNCHER_OPEN = (1 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_DRM_SET_FD = (2 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_ACTIVATE_VT = (3 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (4 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_ACTIVATE_VT = (2 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST),
};
enum weston_launcher_server_opcode {
@ -53,7 +52,7 @@ struct weston_launcher_open {
struct weston_launcher_activate_vt {
struct weston_launcher_message header;
int vt;
signed char vt;
};
struct weston_launcher_reply {

View File

@ -0,0 +1,214 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 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 "window-wayland.h"
#include "window-private.h"
#include "boxes-private.h"
#include "stack-tracker.h"
#include "meta-wayland-surface.h"
struct _MetaWindowWayland
{
MetaWindow parent;
};
struct _MetaWindowWaylandClass
{
MetaWindowClass parent_class;
};
G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW)
static void
meta_window_wayland_manage (MetaWindow *window)
{
MetaDisplay *display = window->display;
meta_display_register_wayland_window (display, window);
{
MetaStackWindow stack_window;
stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
stack_window.wayland.meta_window = window;
meta_stack_tracker_record_add (window->screen->stack_tracker,
&stack_window,
0);
}
}
static void
meta_window_wayland_unmanage (MetaWindow *window)
{
{
MetaStackWindow stack_window;
stack_window.any.type = META_WINDOW_CLIENT_TYPE_WAYLAND;
stack_window.wayland.meta_window = window;
meta_stack_tracker_record_remove (window->screen->stack_tracker,
&stack_window,
0);
}
meta_display_unregister_wayland_window (window->display, window);
}
static void
meta_window_wayland_ping (MetaWindow *window,
guint32 serial)
{
meta_wayland_surface_ping (window->surface, serial);
}
static void
meta_window_wayland_delete (MetaWindow *window,
guint32 timestamp)
{
meta_wayland_surface_delete (window->surface);
}
static void
meta_window_wayland_kill (MetaWindow *window)
{
/* TODO */
}
static void
meta_window_wayland_focus (MetaWindow *window,
guint32 timestamp)
{
meta_display_set_input_focus_window (window->display,
window,
FALSE,
timestamp);
}
static void
meta_window_wayland_move_resize_internal (MetaWindow *window,
int gravity,
MetaRectangle requested_rect,
MetaRectangle constrained_rect,
MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result)
{
g_assert (window->frame == NULL);
/* For wayland clients, the size is completely determined by the client,
* and while this allows to avoid some trickery with frames and the resulting
* lagging, we also need to insist a bit when the constraints would apply
* a different size than the client decides.
*
* Note that this is not generally a problem for normal toplevel windows (the
* constraints don't see the size hints, or just change the position), but
* it can be for maximized or fullscreen.
*/
/* First, save where we would like the client to be. This is used by the next
* attach to determine if the client is really moving/resizing or not.
*/
window->expected_rect = constrained_rect;
if (flags & META_IS_WAYLAND_RESIZE)
{
/* This is a call to wl_surface_commit(), ignore the constrained_rect and
* update the real client size to match the buffer size.
*/
window->rect.width = requested_rect.width;
window->rect.height = requested_rect.height;
}
if (constrained_rect.width != window->rect.width ||
constrained_rect.height != window->rect.height)
{
/* We need to resize the client. Resizing is in two parts:
* some of the movement happens immediately, and some happens as part
* of the resizing (through dx/dy in wl_surface_attach).
*
* To do so, we need to compute the resize from the point of the view
* of the client, and then adjust the immediate resize to match.
*
* dx/dy are the values we expect from the new attach(), while deltax/
* deltay reflect the overall movement.
*/
MetaRectangle old_rect;
MetaRectangle client_rect;
int dx, dy;
int deltax, deltay;
meta_window_get_client_root_coords (window, &old_rect);
meta_rectangle_resize_with_gravity (&old_rect,
&client_rect,
gravity,
constrained_rect.width,
constrained_rect.height);
deltax = constrained_rect.x - old_rect.x;
deltay = constrained_rect.y - old_rect.y;
dx = client_rect.x - constrained_rect.x;
dy = client_rect.y - constrained_rect.y;
if (deltax != dx || deltay != dy)
*result |= META_MOVE_RESIZE_RESULT_MOVED;
window->rect.x += (deltax - dx);
window->rect.y += (deltay - dy);
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
meta_wayland_surface_configure_notify (window->surface,
constrained_rect.width,
constrained_rect.height);
}
else
{
/* No resize happening, we can just move the window and live with it. */
if (window->rect.x != constrained_rect.x ||
window->rect.y != constrained_rect.y)
*result |= META_MOVE_RESIZE_RESULT_MOVED;
window->rect.x = constrained_rect.x;
window->rect.y = constrained_rect.y;
}
}
static void
meta_window_wayland_init (MetaWindowWayland *window_wayland)
{
}
static void
meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
{
MetaWindowClass *window_class = META_WINDOW_CLASS (klass);
window_class->manage = meta_window_wayland_manage;
window_class->unmanage = meta_window_wayland_unmanage;
window_class->ping = meta_window_wayland_ping;
window_class->delete = meta_window_wayland_delete;
window_class->kill = meta_window_wayland_kill;
window_class->focus = meta_window_wayland_focus;
window_class->move_resize_internal = meta_window_wayland_move_resize_internal;
}

View File

@ -0,0 +1,44 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 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_WINDOW_WAYLAND_H
#define META_WINDOW_WAYLAND_H
#include <meta/window.h>
G_BEGIN_DECLS
#define META_TYPE_WINDOW_WAYLAND (meta_window_wayland_get_type())
#define META_WINDOW_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_WAYLAND, MetaWindowWayland))
#define META_WINDOW_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_WAYLAND, MetaWindowWaylandClass))
#define META_IS_WINDOW_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_WAYLAND))
#define META_IS_WINDOW_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_WAYLAND))
#define META_WINDOW_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_WAYLAND, MetaWindowWaylandClass))
GType meta_window_wayland_get_type (void);
typedef struct _MetaWindowWayland MetaWindowWayland;
typedef struct _MetaWindowWaylandClass MetaWindowWaylandClass;
#endif

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