Compare commits

...

91 Commits

Author SHA1 Message Date
Carlos Garnacho
3ed80495e0 compositor: emit grab-op-begin/end signals on plugin grabs
This makes it possible to track there grabs triggered this way, in
addition to the ones handled by mutter.
2014-06-25 16:38:29 +02:00
Carlos Garnacho
f13c86d651 gesture-tracker: Implement threshold-based sequence rejection
If a sequence moves past a certain distance without being used by a
gesture, reject it so clients may see and react to it ASAP. This makes
gestures to be began by initially quasi-static touchpoints, in addition to
quasi-simultaneous.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
be2ca66735 wayland: Export meta_wayland_touch_cancel()
This will be necessary in order to hook the gesture tracker
to clients.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
2df807549e frames: Keep information about the ongoing grab operation, and retry if needed.
When a passive touch grab is rejected over the frame, management is punted to
the frame itself, and pointer events emulated, but the attempt to transfer the
grab from the GDK connection to the Clutter one fails with AlreadyGrabbed, and
will fail until the Clutter connection receives the XI_TouchEnd resulting from
XIRejectTouch, gotten after the XI_ButtonPress on the GDK connection.

In order to bypass this shortcoming, store the current grab operation on the
frame as long as the button is pressed, so it is retried once on the next
motion event happening during frame dragging, that will have a recent enough
timestamp to succeed. If no grabbing succeeded, the current grab operation
data will be reset on GDK_BUTTON_RELEASE.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
66cdb1bb71 backend: Use the most recent event time on replayed touch events
When a touch sequence is passively grabbed and later rejected, events
will be replayed on the next client in propagation order, although those
events (either transformed to pointer events or not) will contain the
original timestamps, this will make grabs fail with InvalidTime if triggered
from the replayed ButtonPress/TouchBegin handler.

In order to work around this, store the most recent event time (presumably
gotten from the XI_TouchEnd caused by the passive grab being rejected), and
use that time on the events being replayed afterwards and grabs, so we don't
possibly fail with InvalidTime if those events result in a compositor grab.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
8030a2972e display: Set an X11 passive touch grab on the root window
Touch events will be caught first by the compositor this way,
whenever the MetaGestureTracker notifies of the accepted/rejected
state of a sequence, XIAllowTouchEvents() will be called on it
accordingly, so it is handled exclusively by the compositor or
punted to clients.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ba086dea8c events: Hook MetaGestureTracker to display event processing
Events aren't actually consumed by the MetaGestureTracker, but it
rather defines whether the event will reach clients, or the stage.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
6a02d7dfa3 backend: Ensure touch event coordinates are translated to the stage's
Now that those events are going to be received, coordinates translation
should also happen on those.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
c5db56da5c display: Add a getter for the gesture tracker
The MetaDisplay will contain a global MetaGestureTracker,
shared through this getter.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
b5c605df5e core: Add MetaGestureTracker
This object tracks both touch sequences happening on the stage and
gestures attached to the stage actor. When a gesture emits
::gesture-begin, All triggering sequences and future ones will be
marked as "accepted" by the compositor, and events will be listened
for meanwhile there are active gestures.

If a sequence goes unclaimed for a short time, it will be
automatically "denied", and punted to the client or shell element
below.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
4ad2865cce events: Update current time on CLUTTER_TOUCH_BEGIN events
Just as with key/button press events, update the current interaction
time when a touch begins on a window.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
b9687d1a72 ui: Remove unneeded code
There's no way now that GDK will hold a grab, so it is safe to remove
this now.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
66d18fcc55 x11/events: Filter out all pointer/touch GDK events
Mutter does its own input event processing, including for the places
where interaction is wanted with the remaining GTK UI elements
(frames), so GDK is largely disposable.

Even though the GDK display connection remains, and events will
be delivered over there due to event selections on that display,
all pointer and touch events will be handled and filtered out by
the GDK filter function.

The dedicated event processing meant for frames in src/ui/ui.c
now hooks to the display connection through
meta_display_events_x11_add_func(), added to let all event filters
run and stop processing at a single point.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
321cd5d85f ui: Remove XI_TouchBegin handling from window frame event handlers
This is now unnecessary as only pointer events are selected, so pointer
emulation will take care of sending only pointer events.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ae91de5d03 frame: Only select for ButtonPress/Release/Motion/Crossing
Touch events are largely ignored on GdkEvent emulation, so only
make frames receive pointer events, only the pointer emulating
touch will be reported, and any other further touches will be
ignored, which is about the behavior we want. This makes window
dragging possible again on touch.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
7247b8d81b backend-x11: Remove pointless goto
The function is not as complex as needing that, plus it always jumped
anytime bypass_clutter is TRUE, so make all conditional code depend on
that.
2014-06-25 15:17:12 +02:00
Florian Müllner
97f2de37e1 Bump version to 3.13.3
Update NEWS.
2014-06-24 23:42:06 +02:00
Florian Müllner
967b6c33df window: Add user_op parameter to update_monitor()
When workspaces-only-on-primary is set and a window is moved back to the
primary, we also move it to the active workspace to avoid the confusion
of a visible window suddenly disappearing when crossing the monitor border.
However when the window is not actually moved by the user, preserving the
workspace makes more sense - we already do this in some cases (e.g. when
moving between primary monitors), but miss others (unplugging the previous
monitor); just add an explicit user_op parameter as used elsewhere to cover
all exceptions.

https://bugzilla.gnome.org/show_bug.cgi?id=731760
2014-06-24 23:42:06 +02:00
Florian Müllner
00c7a27732 window: Keep track of preferred output
Remember the last monitor a window was moved to by user action and
try to move it back on monitor changes; this should match user
expectations much better when a monitor is unplugged temporarily.

https://bugzilla.gnome.org/show_bug.cgi?id=731760
2014-06-24 23:42:06 +02:00
Florian Müllner
048ba353c4 window: Don't make windows on non-primaries sticky on restart
When workspaces-only-on-primary is set, a window can be on all
workspaces either because it is on a non-primary workspace, or
because it was explicitly made sticky. Only the latter is reflected
in _NET_WM_STATE, but both will result in a "magic" _NET_WM_DESKTOP,
which we (and probably other WMs) use to set the initial sticky state.
So to avoid confusing other WMs (or ourselves), make sure to only
have _NET_WM_STATE_STICKY reflected in _NET_WM_DESKTOP when unmanaging.
2014-06-24 23:01:59 +02:00
Florian Müllner
555e2f6de2 Revert "window: Move placement code from the constraints path"
Window state like maximization and minimization should be preserved
over restarts - in a patch review, this would qualify as "needs-work",
so revert the cleanup until the issues are fixed.

This reverts commit dc6decefb5.
2014-06-24 22:59:06 +02:00
Jasper St. Pierre
ff8d5281f0 frames: Simplify the clip region calculation
Since GTK+ already clips to the extended region for us, there's no need
to combine the two. This does lose the fast-path, but I don't actually
expect this to fire, as when we're composited, we really won't ever get
partial exposes.
2014-06-21 13:50:44 -04:00
Jasper St. Pierre
4f9b994e73 frames: Don't bother painting the background
GDK (and also GTK+!) do this for us already.
2014-06-21 13:50:43 -04:00
Jasper St. Pierre
b8b0dc5c78 frames: Hackily adapt to GTK+ drawing changes
mutter is quite bad at using GTK+ correctly, relying on dumb things
like the single-buffering stuff. Hack up a temporary fix for the
newer GTK+ rendering changes.
2014-06-21 13:50:36 -04:00
Nikita Churaev
d0cafab836 Change shadow radiuses to match new Adwaita more or less
Exact simmilarity is not possible yet due to different blurring algorithms.

https://bugzilla.gnome.org/show_bug.cgi?id=731866
2014-06-19 11:55:24 +02:00
Jasper St. Pierre
24d7c5ebe3 compositor: Simplify meta_window_actor_set_updates_frozen
Since we always call it with the same value, just push that
value into the implementation.
2014-06-17 13:10:42 -04:00
Jasper St. Pierre
dc6decefb5 window: Move placement code from the constraints path
This way, it's implemented as a special case in move_resize_internal,
which makes it a lot easier to manage.
2014-06-17 11:40:49 -04:00
Jasper St. Pierre
25d7e48077 constraints: Clean up logical operations
The logical version of the bitwise XOR operator ^ is !=. I don't
know why XOR was even used in the first place.
2014-06-17 11:21:25 -04:00
Jasper St. Pierre
b0b8f37240 window: Save the buffer_rect internally
Rather than calculate it speculatively with the current properties
which may be too new or too out of date, make sure it always fits
with the proper definition. We update it when we update the toplevel
window for X11, and when a Wayland surface is committed with a newly
attached buffer.
2014-06-17 11:15:32 -04:00
Jasper St. Pierre
188e4e1b92 window: Rename get_input_rect to get_buffer_rect
With get_input_region existing, get_input_rect is a misnomer. Really,
it's about the geometry of the output surface, and it's only used that
way in the compositor code.

Way back when in GNOME 3.2, get_input_rect was added when we added
invisible borders. get_outer_rect was always synonymous with server-side
geometry of the toplevel. get_outer_rect was used for both user-side
policy (the "frame rect") and to get the geometry of the window.

Invisible borders were meant to extend the input region of the frame
window silently. Since most users of get_outer_rect cared about the
frame rect, we kept that the same and added a new method, get_input_rect
to get the full rect of the framed window with all invisible borders for
input kept on.

As time went on and CSD and Wayland became a reality, the relationship
between the server-side geometry and the "frame rect" became more
complicated, as can be evidenced by the recent commits. Since clients
don't tend to be framed anymore, they set their own input region.

get_buffer_rect is also sort of a poor name, since X11 doesn't really
have buffers, but we don't really have many other alternatives.

This doesn't change any of the code, nor the meaning. It will always
refer to the rectangle where the toplevel should be placed.
2014-06-17 10:33:52 -04:00
Jasper St. Pierre
9d5273bb15 window: Fix get_input_rect in a hacky way
All of the users of get_input_rect don't actually want a synthesized
input rect based off of the current margins. What they really want is
the last-configured size of the toplevel window.

Since we don't properly track this anymore in the generic MetaWindow,
use XGetWindowAttributes to fetch a server-side rectangle. This is a
bad layer violation, but since the window geometry code will have to
be rewritten anyway for the Wayland set_window_geometry, let's just
push a hacky fix for now.
2014-06-16 18:34:07 -04:00
Jasper St. Pierre
3c0fae74f1 window: Move get_toplevel_xwindow to window-x11 2014-06-16 18:29:38 -04:00
Jasper St. Pierre
86dae6d4c7 theme: Replace char array element comparisons with strncmp
https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:12:53 -04:00
Jasper St. Pierre
d06600aeb0 theme: Remove dead code
While the comment claims that we may want to keep this around
for optimization purposes, the operations are raw bitmap operations
that would be cleaner done in cairo.

https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:12:52 -04:00
Jasper St. Pierre
895a3d1f39 theme: Properly indent code
s/tabs/spaces/

https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:11:32 -04:00
Jasper St. Pierre
381ef5c683 theme: Consolidate unused ops
https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:11:00 -04:00
Jasper St. Pierre
62097897be theme: Remove unused RECTANGLE code
https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:04:59 -04:00
Jasper St. Pierre
2d2c47ba49 display: Remove unused variable 2014-06-12 17:46:23 -04:00
Jasper St. Pierre
89cdfc9194 display: Use G_SOURCE_CONTINUE / G_SOURCE_REMOVE 2014-06-12 17:46:23 -04:00
Jasper St. Pierre
ad60ea9e0e display: Use meta_window_has_pointer instead of XQueryPointer 2014-06-12 17:46:23 -04:00
Florian Müllner
a7350475e8 workspace: Extend builtin struts to screen edge when possible
Struts are defined in terms of screen edges, so expand the rectangles
we get via set_builtin_struts() accordingly. However we do want to
allow chrome on edges between monitors, in which case the expansion
would render an entire monitor unusable - don't expand the rectangles
in that case, which means we will only use them for constraining
windows but ignore them for the client-visible _NET_WORKAREA property.

https://bugzilla.gnome.org/show_bug.cgi?id=730527
2014-06-12 15:28:46 +02:00
Florian Müllner
f3d7c9cff9 testboxes: Update test cases
Who cares? We do now ...

https://bugzilla.gnome.org/show_bug.cgi?id=730527
2014-06-12 15:28:46 +02:00
Florian Müllner
906cbeed61 boxes: Ignore struts that don't attach to the side they claim
Like the _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL client properties,
_NET_WORKAREA is defined in terms of screen geometry rather than
taking individual monitors into account. However we do want to
allow system chrome to be attached to a monitor edge rather than
a screen edges under some circumstances. As not all clients can
be assumed to deal gracefully with the resulting workarea, use
those "struts" only internally for constraining windows, but
ignore them when exporting _NET_WORKAREA.

https://bugzilla.gnome.org/show_bug.cgi?id=730527
2014-06-12 15:28:42 +02:00
Florian Müllner
0fccb0fc86 testboxes: Fix find_closest_point_to_line() test
Eeeks, testing floating points for equality ...
2014-06-12 01:39:54 +02:00
Florian Müllner
8100cefd4c screen: Split workspace initialization from meta_screen_new()
Since commit 8b2b65246a, we assume that the compositor always
exists. Alas, the assumption is wrong - the compositor is currently
initialized after the screen, but meta_screen_new() itself may
call a compositor function if initialization involves a workspace
switch (which will happen when meta_workspace_activate() is called
more than once and for different workspaces - or in other words,
when _NET_CURRENT_DESKTOP is set and not 0).
So carefully split out the offending bits and only call them after
the compositor has been initialized.

https://bugzilla.gnome.org/show_bug.cgi?id=731332
2014-06-11 23:35:34 +02:00
Florian Müllner
d7e99a3f86 prefs: Queue change notification when app menu visibility changed
Toggling the option should have an immediate effect, not only on
frame/state changes.
2014-06-11 23:34:09 +02:00
Jasper St. Pierre
6af944fe2c native: Add a warp_pointer implementation
Use the new clutter_evdev_warp_pointer method to implement it.
2014-06-11 16:42:05 -04:00
Jasper St. Pierre
12fc394b92 display: Fix the logic for moving attached dialogs
If we have a tree of a window, a non-attached dialog, and then an
attached dialog, we want to move the second window, not the attached
dialog or the topmost. In other words, we want to move the first
non-attached window, or the first "freefloating window".

This happens in Firefox, whose Preferences dialog is freefloating,
but suboptions of those are modal dialogs.
2014-06-11 16:42:05 -04:00
Jasper St. Pierre
53814fefc1 Move all X11 event processing to a new file in x11/ 2014-06-11 16:28:45 -04:00
Jasper St. Pierre
e87a01c80b wayland-touch: Rearrange header slightly 2014-06-11 16:28:45 -04:00
Jasper St. Pierre
21d7c1a850 wayland-pointer: Remove useless initialization
There is no way this value will ever be read, because we set the
cursor_surface to NULL, this is set at the same time as cursor_surface,
and it's only read if cursor_surface is non-NULL.
2014-06-11 15:15:58 -04:00
Jasper St. Pierre
e33c58297d wayland-surface: Subsurfaces start out in synchronous mode 2014-06-11 12:34:44 -04:00
Jasper St. Pierre
5350120db4 wayland-surface: Fix whitespace 2014-06-11 12:34:17 -04:00
Jasper St. Pierre
0997cf7fee Update .gitignore
These aren't generated in the data/ subdir.
2014-06-11 09:24:59 -04:00
Florian Müllner
af3aae7295 meta-window-actor: Don't add shadows to popups if the toolkit already does
GTK+ will add its own shadows client-side, so we don't need to anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=731353
2014-06-10 13:40:33 +02:00
Florian Müllner
98e219da4b shadow-factory: Make sure to never use a negative spread
The smallest possible spread corresponds to an unblurred shadow, which
neither grows nor shrinks - thus the spread should be zero not negative
as returned by our current calculation.

https://bugzilla.gnome.org/show_bug.cgi?id=731353
2014-06-10 13:40:32 +02:00
Florian Müllner
fba022cc06 window-x11: Handle legacy fullscreen requests
Doing this on the actual resize requests makes more sense than
handling it as a window-manager imposed constraints, so move
the code accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=730681
2014-06-09 22:27:33 +02:00
Florian Müllner
3f6c6f1dd9 constraints: Translate frame to client rect for legacy fullscreen check
Stupid apps fullscreen themselves by resizing the client window to
monitor size. A monitor-sized frame rect on the other hand is perfectly
normal on monitors without struts - stop force-fullscreening those
and catch the real baddies instead.

https://bugzilla.gnome.org/show_bug.cgi?id=730681
2014-06-09 21:28:50 +02:00
Florian Müllner
ebc2e7221b window-x11: Fix silly regression
First we figure out the window type, then we ignore it - ouch.
2014-06-07 12:00:17 +02:00
Rico Tzschichholz
7cb30ced23 configure.ac: Modernize autoconf/libtool dependencies and macro usage 2014-06-05 18:05:19 +02:00
Rico Tzschichholz
7b449ac56c configure.ac: Group hard-dependencies together rather than split them up 2014-06-05 18:05:14 +02:00
Rico Tzschichholz
724953101d configure.ac: Drop obsolete shape/xsync confflags
In addition to 20a0eb9809
2014-06-05 18:04:59 +02:00
Rico Tzschichholz
8734477d52 meta: Add generated meta-version.h
Avoid populating *_VERSION constants through cflags in pkg-config-file
which could be overridden by the project using it. Properly prefix the
defines with META_ to make gi-scanner happy.
2014-06-05 14:05:16 +02:00
Rico Tzschichholz
ec8ba4b5f9 build: Move data files to their dedicated subfolder 2014-06-05 10:50:15 +02:00
Carlos Garnacho
2250865eb6 wayland: Implement the server side bits of wl_touch_interface
Clutter touch events are translated into events being sent down
the interface resource, with the exception of FRAME/CANCEL events,
which are handled directly via an evdev event filter.

The seat now announces invariably the WL_SEAT_CAPABILITY_TOUCH
capability, this should be eventually updated as devices come and
go.

The creation of MetaWaylandTouchSurface structs is dynamic, attached
to the lifetime of first/last touch on the client surface, and only
if the surface requests the wl_touch interface. MetaWaylandTouchInfo
structs are created to track individual touches, and are locked to
a single MetaWaylandTouchSurface (the implicit grab surface) determined
on CLUTTER_TOUCH_BEGIN.

https://bugzilla.gnome.org/show_bug.cgi?id=724442
2014-06-04 23:37:45 +02:00
Rico Tzschichholz
847a3bbee3 build: Fix some warnings and clean up a bit 2014-06-04 19:31:37 +02:00
Rico Tzschichholz
410a002ddd build: Do not distribute generated desktop-files 2014-06-04 16:13:11 +02:00
Rico Tzschichholz
8766db2593 common: Do not leak MetaResizePopup to the public api 2014-06-04 15:53:29 +02:00
Jasper St. Pierre
e362227514 window-x11: Don't ever send ConfigureNotifies for OR windows
There's a race here. If an OR window hides itself, moves, and then shows
itself, we will send a ConfigureNotify for the old size of the window
and might receive it after the client moves itself, causing us to show
the window at the wrong location.

Simply not sending the ConfigureNotify is the easiest thing to do.
2014-06-03 11:35:20 -04:00
Jasper St. Pierre
da311f266d window: Make sure to update client_rect for OR windows too
Before we unmanage, we send a ConfigureNotify to clients to let them
know if their frame is destroyed. We do this for OR windows too, even if
we really probably shouldn't.

This is based off of the client_rect. Since we listen to ConfigureNotify
on OR windows, we'll receive the event. If we don't ever update the
client_rect when moving or resizing OR windows, then we'll send
ourselves a ConfigureNotify for a 0x0 size and then think that the
client chose a new size for itself. Since our get_paint_volume is based
on that rectangle, but the TFP code inside Cogl uses XGetGeometry
itself, we get weird flickering artifacts.
2014-06-03 11:35:19 -04:00
Rico Tzschichholz
f5a4e996a8 display: Remove the screen from get_tab_list 2014-06-03 14:40:15 +02:00
Florian Müllner
a7f083897f frames: Only skip updating prelight when both control and state match
prelit_control is used for both prelight and pressed states, so the early
return in update_prelit_control() misses the case where prelit_control
already matches the control we are updating, but its state is PRESSED
rather than PRELIGHT. Fix the condition to not have pressed controls
linger around erroneously.

https://bugzilla.gnome.org/show_bug.cgi?id=731058
2014-06-02 23:49:48 +02:00
Florian Müllner
e2105dc721 frames: Fix pressed state of window menu buttons
Since window menus have been moved to the compositor, the pressed
state of the corresponding window buttons is messed up, as it is
reset immediately when getting a LeaveNotify event due to the
compositor taking a grab. Fix this by ignoring that particular
event.

https://bugzilla.gnome.org/show_bug.cgi?id=731058
2014-06-02 23:49:48 +02:00
Florian Müllner
b64548ee1f Pass button_rect when opening window menu from button
When opening the window menu without an associated control - e.g.
by right-clicking the titlebar or by keyboard - using coordinates
for the menu position is appropriate. However when the menu is
associated with a window button, the expected behavior in the
shell can be implemented much easier with the full button geometry:
the menu will point to the center of the button's bottom edge
rather than align to the left/right side of the titlebar as it
does now, and the clickable area where a release event does not
dismiss the menu will match the actual clickable area in mutter.

So add an additional show_window_menu_for_rect() function and
use it when opening the menu from a button.

https://bugzilla.gnome.org/show_bug.cgi?id=731058
2014-06-02 23:49:48 +02:00
Jasper St. Pierre
53425fa721 window: Make sure not to respond to input events on OR windows
This can happen since we select for events on the root window, and
clients themselves might not select for input, meaning the X server
will bubble up. Just do nothing and ignore the event in this case.

This should hopefully fix some of the

Window manager warning: Log level 8: meta_window_raise: assertion '!window->override_redirect' failed
Window manager warning: Log level 8: meta_window_focus: assertion '!window->override_redirect' failed

spam that people have been seeing.
2014-06-02 15:51:41 -04:00
Jonas Ådahl
048f035d30 wayland: Scale smooth scroll events to pointer motion coordinate space
Smooth scroll event vectors from clutter have the same dimensions as the
ones from from Xi2, i.e. where 1.0 is 1 discrete scroll step. To scale
these to the coordinate space used by wl_pointer.axis
vertical/horizontal scroll events, multiply the vector by 10.

https://bugzilla.gnome.org/show_bug.cgi?id=729601
2014-05-31 14:22:10 +02:00
Jasper St. Pierre
b32c837df9 window: Fix placement not actually placing windows
Since we often call meta_window_move_resize_now immediately after
mapping a window, we need to make sure that the placed coordinates
are saved in the unconstrained_rect. Ideally, placement positions
wouldn't be part of the constraints system, but instead are just
done inside meta_window_move_resize_internal as part of a special
path.

We're still working out the kinks of one large-scale refactor, so
it's best not to do another one while the first is going on. This
would be a great future cleanup, though: untangling constraints
and placement, alongside the force_placement state machine and
friends.
2014-05-29 14:09:57 -04:00
Jasper St. Pierre
dd03a76d51 place: Reindent 2014-05-29 13:58:08 -04:00
Jasper St. Pierre
806a666950 Make the native backend build-optional 2014-05-29 12:43:08 -04:00
Jasper St. Pierre
b240a5e819 keybindings: Only add VT keybindings if we're using the native backend 2014-05-29 12:43:07 -04:00
Jasper St. Pierre
fe823b3553 events: Improve check for native backend 2014-05-29 12:43:07 -04:00
Florian Müllner
d380d30ef4 Update (allow-none) annotations
The annotation has been deprecated in favor of (nullable) and/or
(optional).
2014-05-28 21:55:03 +02:00
Jasper St. Pierre
1fe5b3e7d5 window: Construct the frame before the initial move_resize
This ensures sure that the initial ConfigureRequest we make is
correct.
2014-05-28 11:47:14 -04:00
Jasper St. Pierre
a8df208a5c window-x11: Keep flags where they're used
Just a simple code cleanup
2014-05-28 11:43:11 -04:00
Jasper St. Pierre
f3f3c94831 frame: Don't reset window->rect 2014-05-28 10:50:23 -04:00
Jasper St. Pierre
6e06648f7a window: Refactor all move/resize operations to be in frame rect space
For Wayland, we want to have everything possible in terms of the frame
rect, or "window geometry" as the Wayland protocol calls it, in order
to properly eliminate some flashing when changing states to fullscreen
or similar.

For this, we need to heavily refactor how the code is structured, and
make it so that meta_window_move_resize_internal is specified in terms
of the frame rect coordinate space, and transforming all entry points
to meta_window_move_resize_internal.

This is a big commit that's hard to tear apart. I tried to split it
as best I can, but there's still just a large amount of changes that
need to happen at once.

Expect some regressions from this. Sorry for any temporary regression
that this might cause.
2014-05-27 15:44:34 -04:00
Jasper St. Pierre
afb41f715b core: Make META_CORE_GET_FRAME_RECT return the "frame rect"
We have two different coordinate spaces here. One is the rectangle
returned by meta_window_get_frame_rect, which is called the "frame
rect" or "the window geometry", which includes visible frame borders
but not invisible frame borders. The other is "frame->rect" which
corresponds to the frame's server geometry. That is, it includes
both visible and invisible frame borders.

These two were of course the same until we introduced invisible
frame borders, and an executive decision was made to make
meta_window_get_frame_rect return the rectangle bounding the
visible portions of the frame.

As time went on, the "frame rect" turned out to be more useful when
making decisions upon, since the user often doesn't think about the
invisible window geometry as part of the window.

We already calculate what amounts to the "frame rect" in the theme
code, so just change META_CORE_GET_FRAME_RECT to consume that
directly.
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
19d26dde92 core: Convert GET_FRAME_WIDTH / GET_FRAME_HEIGHT to GET_FRAME_RECT
Since we're going to be calling meta_window_get_frame_rect in here
soon, I'd rather it be one method call, rather than two. We can't
put it at the toplevel, since that might cause infinite recursion
(e.g. meta_core_get calls meta_window_get_frame_rect calls
meta_ui_get_frame_borders calls meta_core_get, ...)
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
4acb902423 window: Correct the anchoring of drag moving / resizing
Now that meta_window_move_resize and friends act in frame rect
coordinates, we need to convert the initial grab_anchor_window_pos
storage to be in frame rect coordinates as well.
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
626516d12e window: Remove meta_window_move as well
Move to meta_window_move_frame everywhere...
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
1c94df2553 window: Replace meta_window_resize_with_gravity with a frame-rect variant
More low-hanging fruit for our window geometry cleanups...
2014-05-27 15:44:33 -04:00
84 changed files with 4566 additions and 3099 deletions

View File

@@ -1,35 +0,0 @@
Makefile
Makefile.in
aclocal.m4
confdefs.h
config.cache
config.guess
config.h
config.log
config.status
config.sub
configure
configure.scan
libtool
ltconfig
ltmain.sh
stamp-h
stamp-h.in
stamp-h1
stamp.h
version.h
config.h.in
install-sh
missing
mkinstalldirs
INSTALL
intl
ABOUT-NLS
COPYING
intltool-*
metacity.spec
autom4te.cache
compile
depcomp
omf.make
xmldocs.make

21
.gitignore vendored
View File

@@ -3,6 +3,7 @@ Makefile.in
Makefile.in.in
aclocal.m4
autom4te.cache
build-aux
compile
config.guess
config.h
@@ -19,11 +20,11 @@ libtool
ltmain.sh
missing
.deps
src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter.desktop
src/mutter-wayland.desktop
50-mutter-navigation.xml
50-mutter-system.xml
50-mutter-windows.xml
mutter.desktop
mutter-wayland.desktop
*.o
*.a
*.lo
@@ -32,10 +33,6 @@ src/mutter-wayland.desktop
*.swp
*.gir
*.typelib
tidy-enum-types.[ch]
tidy-marshal.[ch]
stamp-tidy-enum-types.h
stamp-tidy-marshal.h
stamp-h1
*.gmo
*.make
@@ -44,8 +41,6 @@ stamp-it
.intltool-merge-cache
POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
libmutter.pc
mutter
org.gnome.mutter.gschema.valid
@@ -66,9 +61,6 @@ test-focus
test-gravity
test-resizing
test-size-hints
# We can't say just "wm-tester" here or it will ignore the directory
# rather than the binary
src/wm-tester/wm-tester
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]
@@ -84,6 +76,7 @@ src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
src/meta/meta-version.h
doc/reference/*.args
doc/reference/*.bak
doc/reference/*.hierarchy

View File

@@ -1,10 +1,13 @@
SUBDIRS=src po doc
SUBDIRS = data src po doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
DISTCLEANFILES = \
intltool-extract \
intltool-merge \
intltool-update \
po/stamp-it \
po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

13
NEWS
View File

@@ -1,3 +1,16 @@
3.13.3
======
* Improve behavior of window buttons with compositor menus [Florian; #731058]
* Implement touch support on wayland [Carlos; #724442]
* Update window shadows [Nikita; #731866]
* Keep windows on the preferred output [Florian; #731760]
* Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332,
#730527, #662962]
Contributors:
Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz
3.13.2
======
* Add basic HiDPI support on wayland [Adel; #728902]

View File

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

View File

@@ -1,9 +1,8 @@
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [2])
m4_define([mutter_micro_version], [3])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -14,6 +13,7 @@ AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
@@ -40,12 +40,14 @@ GETTEXT_PACKAGE=mutter
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
IT_PROG_INTLTOOL([0.34.90])
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
IT_PROG_INTLTOOL([0.41])
AC_PROG_CC
AC_ISC_POSIX
AC_PROG_CC_C_O
AC_PROG_INSTALL
AC_HEADER_STDC
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG([0.21])
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0()
@@ -75,8 +77,13 @@ MUTTER_PC_MODULES="
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
xcursor
$CLUTTER_PACKAGE >= 1.17.5
clutter-wayland-1.0
clutter-wayland-compositor-1.0
clutter-egl-1.0
cogl-1.0 >= 1.17.1
wayland-server >= 1.4.93
upower-glib >= 0.99.0
gnome-desktop-3.0
"
@@ -107,26 +114,12 @@ AC_ARG_WITH(libcanberra,
[disable the use of libcanberra for playing sounds]),,
with_libcanberra=auto)
AC_ARG_ENABLE(xsync,
AC_HELP_STRING([--disable-xsync],
[disable mutter's use of the XSync extension]),,
enable_xsync=auto)
AC_ARG_ENABLE(shape,
AC_HELP_STRING([--disable-shape],
[disable mutter's use of the shaped window extension]),,
enable_shape=auto)
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"])
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@@ -191,17 +184,20 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93 libdrm libsystemd"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@@ -293,17 +289,6 @@ fi
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
HOST_ALIAS=$host_alias
AC_SUBST(HOST_ALIAS)
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
fi
AC_SUBST(GDK_PIXBUF_CSOURCE)
AC_PATH_PROG(ZENITY, zenity, no)
if test x"$ZENITY" = xno; then
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
@@ -386,6 +371,7 @@ changequote([,])dnl
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
doc/man/Makefile
doc/reference/Makefile
@@ -393,6 +379,7 @@ doc/reference/meta-docs.sgml
src/Makefile
src/libmutter.pc
src/compositor/plugins/Makefile
src/meta/meta-version.h
po/Makefile.in
])

View File

@@ -1,3 +1,36 @@
defaultcursordir = $(datadir)/mutter/cursors
desktopfiles_in_files = \
mutter.desktop.in \
mutter-wayland.desktop.in
desktopfilesdir = $(datadir)/applications
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
dist_defaultcursor_DATA = left_ptr.png
@INTLTOOL_DESKTOP_RULE@
xml_in_files = \
50-mutter-navigation.xml.in \
50-mutter-system.xml.in \
50-mutter-windows.xml.in
xmldir = $(GNOME_KEYBINDINGS_KEYSDIR)
xml_DATA = $(xml_in_files:.xml.in=.xml)
gschema_in_files = \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in
gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml)
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
CLEANFILES = \
$(desktopfiles_DATA) \
$(gsettings_SCHEMAS) \
$(xml_DATA)
EXTRA_DIST = \
$(convert_DATA) \
$(desktopfiles_in_files) \
$(gschema_in_files) \
$(xml_in_files)

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -555,7 +555,7 @@ meta_window_is_monitor_sized
meta_window_is_override_redirect
meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_input_rect
meta_window_get_buffer_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect

View File

@@ -1,8 +1,11 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
data/50-mutter-navigation.xml.in
data/50-mutter-system.xml.in
data/50-mutter-windows.xml.in
data/mutter.desktop.in
data/org.gnome.mutter.gschema.xml.in
data/org.gnome.mutter.wayland.gschema.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c
src/compositor/meta-background.c
@@ -18,9 +21,6 @@ src/core/prefs.c
src/core/screen.c
src/core/util.c
src/core/window.c
src/mutter.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c
src/ui/resizepopup.c
src/ui/theme.c

View File

@@ -1,2 +1 @@
src/metacity.schemas.in
src/mutter-wayland.desktop.in
data/mutter-wayland.desktop.in

View File

@@ -5,37 +5,35 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
INCLUDES= \
AM_CPPFLAGS = \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
-I$(srcdir) \
-I$(srcdir)/backends \
-I$(srcdir)/core \
-I$(srcdir)/ui \
-I$(srcdir)/compositor \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
meta/meta-version.h \
mutter-enum-types.h \
mutter-enum-types.c \
gtk-shell-protocol.c \
@@ -71,18 +69,6 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \
backends/edid.h \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h \
backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
@@ -166,6 +152,8 @@ libmutter_la_SOURCES = \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/gesture-tracker.c \
core/gesture-tracker-private.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@@ -205,6 +193,8 @@ libmutter_la_SOURCES = \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/events.c \
x11/events.h \
x11/group-private.h \
x11/group-props.c \
x11/group-props.h \
@@ -234,6 +224,8 @@ libmutter_la_SOURCES = \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-touch.c \
wayland/meta-wayland-touch.h \
wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
@@ -243,15 +235,31 @@ libmutter_la_SOURCES = \
wayland/window-wayland.c \
wayland/window-wayland.h
if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h
endif
nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS)
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_base_headers = \
libmutterinclude_headers = \
meta/barrier.h \
meta/boxes.h \
meta/common.h \
@@ -280,6 +288,13 @@ libmutterinclude_base_headers = \
meta/window.h \
meta/workspace.h
libmutterinclude_built_headers = \
meta/meta-version.h
libmutterinclude_base_headers = \
$(libmutterinclude_headers) \
$(libmutterinclude_built_headers)
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
@@ -288,9 +303,12 @@ libmutterinclude_extra_headers = \
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_headers) \
$(libmutterinclude_extra_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
bin_PROGRAMS=mutter
mutter_SOURCES = core/mutter.c
@@ -319,7 +337,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
@META_GIR@_EXPORT_PACKAGES = libmutter
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
@@ -339,53 +357,19 @@ testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
@INTLTOOL_DESKTOP_RULE@
desktopfilesdir=$(datadir)/applications
desktopfiles_in_files=mutter.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files)
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
xml_in_files = \
50-mutter-navigation.xml.in \
50-mutter-system.xml.in \
50-mutter-windows.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
CLEANFILES = \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \
$(xml_DATA) \
$(mutter_built_sources) \
$(libmutterinclude_built_headers) \
$(typelib_DATA) \
$(gir_DATA)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
$(IMAGES) \
$(desktopfiles_in_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
EXTRA_DIST = \
$(wayland_protocols) \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \
libmutter.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \

View File

@@ -30,7 +30,10 @@
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
static MetaBackend *_backend;
@@ -100,14 +103,6 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
return TRUE;
}
static void
meta_backend_real_warp_pointer (MetaBackend *backend,
int x,
int y)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
@@ -119,7 +114,6 @@ meta_backend_class_init (MetaBackendClass *klass)
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->warp_pointer = meta_backend_real_warp_pointer;
}
static void
@@ -214,7 +208,7 @@ get_backend_type (void)
return META_TYPE_BACKEND_X11;
#endif
#if defined(CLUTTER_WINDOWING_EGL)
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_BACKEND_NATIVE;
#endif

View File

@@ -28,7 +28,10 @@
#include "display-private.h"
#include "screen-private.h"
#include "meta-backend.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
#endif
#include <string.h>
@@ -171,13 +174,15 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
static struct gbm_device *
get_gbm_device (void)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
else
return NULL;
#endif
return NULL;
}
static void

View File

@@ -210,9 +210,9 @@ make_watch (MetaIdleMonitor *monitor,
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (allow-none): The callback to call when the user has
* @callback: (nullable): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (allow-none): The user data to pass to the callback
* @user_data: (nullable): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
@@ -252,9 +252,9 @@ meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (allow-none): The callback to call when the user is
* @callback: (nullable): The callback to call when the user is
* active again.
* @user_data: (allow-none): The user data to pass to the callback
* @user_data: (nullable): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id

View File

@@ -174,6 +174,20 @@ meta_backend_native_create_cursor_renderer (MetaBackend *backend)
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
}
static void
meta_backend_native_warp_pointer (MetaBackend *backend,
int x,
int y)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
/* XXX */
guint32 time_ = 0;
clutter_evdev_warp_pointer (device, time_, x, y);
}
static void
meta_backend_native_class_init (MetaBackendNativeClass *klass)
{
@@ -183,6 +197,8 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
backend_class->warp_pointer = meta_backend_native_warp_pointer;
}
static void

View File

@@ -51,6 +51,7 @@ struct _MetaBackendX11Private
int xinput_opcode;
int xinput_event_base;
int xinput_error_base;
Time latest_evtime;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
@@ -71,6 +72,7 @@ static void
translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (device_event->event != stage_window)
@@ -88,6 +90,21 @@ translate_device_event (MetaBackendX11 *x11,
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
}
if (!device_event->send_event && device_event->time != CurrentTime)
{
if (device_event->time < priv->latest_evtime)
{
/* Emulated pointer events received after XIRejectTouch is received
* on a passive touch grab will contain older timestamps, update those
* so we dont get InvalidTime at grabs.
*/
device_event->time = priv->latest_evtime;
}
/* Update the internal latest evtime, for any possible later use */
priv->latest_evtime = device_event->time;
}
}
/* Clutter makes the assumption that there is only one X window
@@ -117,6 +134,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
translate_device_event (x11, (XIDeviceEvent *) input_event);
break;
default:
@@ -142,17 +162,14 @@ handle_host_xevent (MetaBackend *backend,
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
{
bypass_clutter = TRUE;
goto out;
}
bypass_clutter = TRUE;
}
maybe_spoof_event_as_stage_event (x11, event);
out:
if (!bypass_clutter)
clutter_x11_handle_event (event);
{
maybe_spoof_event_as_stage_event (x11, event);
clutter_x11_handle_event (event);
}
XFreeEventData (priv->xdisplay, &event->xcookie);
}
@@ -313,6 +330,9 @@ meta_backend_x11_grab_device (MetaBackend *backend,
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
int ret;
if (timestamp != CurrentTime)
timestamp = MAX (timestamp, priv->latest_evtime);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);

View File

@@ -68,7 +68,7 @@ meta_create_color_texture_4ub (guint8 red,
/**
* meta_create_texture_pipeline:
* @src_texture: (allow-none): texture to use initially for the layer
* @src_texture: (nullable): texture to use initially for the layer
*
* Creates a pipeline with a single layer. Using a common template
* makes it easier for Cogl to share a shader for different uses in

View File

@@ -385,6 +385,10 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
g_signal_emit_by_name (display, "grab-op-begin",
meta_plugin_get_screen (plugin),
display->grab_window, display->grab_op);
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
@@ -401,6 +405,10 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
g_return_if_fail (is_modal (display));
g_signal_emit_by_name (display, "grab-op-end",
meta_plugin_get_screen (plugin),
display->grab_window, display->grab_op);
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_have_pointer = FALSE;
@@ -595,7 +603,7 @@ meta_compositor_unmanage (MetaCompositor *compositor)
/**
* meta_shape_cow_for_window:
* @compositor: A #MetaCompositor
* @window: (allow-none): A #MetaWindow to shape the COW for
* @window: (nullable): 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.
@@ -691,12 +699,11 @@ meta_compositor_remove_window (MetaCompositor *compositor,
}
void
meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen)
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
meta_window_actor_sync_updates_frozen (window_actor);
}
void
@@ -1366,3 +1373,12 @@ meta_compositor_show_window_menu (MetaCompositor *compositor,
{
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y);
}
void
meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect)
{
meta_plugin_manager_show_window_menu_for_rect (compositor->plugin_mgr, window, menu, rect);
}

View File

@@ -20,6 +20,7 @@
*/
#include <meta/meta-plugin.h>
#include <meta/meta-version.h>
#include "meta-module.h"
#include <gmodule.h>
@@ -68,7 +69,7 @@ meta_module_load (GTypeModule *gmodule)
(gpointer *)(void *)&register_type) &&
info && register_type)
{
if (info->version_api != MUTTER_PLUGIN_API_VERSION)
if (info->version_api != META_PLUGIN_API_VERSION)
g_warning ("Plugin API mismatch for [%s]", priv->path);
else
{

View File

@@ -374,3 +374,20 @@ meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
if (klass->show_window_menu)
klass->show_window_menu (plugin, window, menu, x, y);
}
void
meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *plugin_mgr,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = plugin_mgr->compositor->display;
if (display->display_opening)
return;
if (klass->show_window_menu_for_rect)
klass->show_window_menu_for_rect (plugin, window, menu, rect);
}

View File

@@ -87,5 +87,10 @@ void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
int x,
int y);
void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *mgr,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
#endif

View File

@@ -121,17 +121,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
/* The first element in this array also defines the default parameters
* for newly created classes */
MetaShadowClassInfo default_shadow_classes[] = {
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
{ "normal", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "dialog", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "modal_dialog", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "border", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
{ "popup-menu", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
{ "dropdown-menu", { 1, 10, 0, 1, 128 }, { 1, 10, 0, 1, 128 } },
{ "attached", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
{ "attached", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
};
G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT);
@@ -189,7 +189,7 @@ meta_shadow_unref (MetaShadow *shadow)
* @window_y: y position of the region to paint a shadow for
* @window_width: actual width of the region to paint a shadow for
* @window_height: actual height of the region to paint a shadow for
* @clip: (allow-none): if non-%NULL specifies the visible portion
* @clip: (nullable): if non-%NULL specifies the visible portion
* of the shadow.
* @clip_strictly: if %TRUE, drawing will be clipped strictly
* to @clip, otherwise, it will be only used to optimize
@@ -496,7 +496,12 @@ get_box_filter_size (int radius)
static int
get_shadow_spread (int radius)
{
int d = get_box_filter_size (radius);
int d;
if (radius == 0)
return 0;
d = get_box_filter_size (radius);
if (d % 2 == 1)
return 3 * (d / 2);

View File

@@ -34,6 +34,7 @@
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-cullable.h"
#include "x11/window-x11.h"
struct _MetaSurfaceActorX11Private
{
@@ -143,7 +144,7 @@ update_pixmap (MetaSurfaceActorX11 *self)
if (priv->pixmap == None)
{
Pixmap new_pixmap;
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
@@ -312,7 +313,7 @@ sync_unredirected (MetaSurfaceActorX11 *self)
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
@@ -404,7 +405,7 @@ create_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
Display *xdisplay = meta_display_get_xdisplay (priv->display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
}

View File

@@ -51,8 +51,7 @@ void meta_window_actor_update_shape (MetaWindowActor *self);
void meta_window_actor_update_opacity (MetaWindowActor *self);
void meta_window_actor_mapped (MetaWindowActor *self);
void meta_window_actor_unmapped (MetaWindowActor *self);
void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen);
void meta_window_actor_sync_updates_frozen (MetaWindowActor *self);
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);

View File

@@ -746,9 +746,11 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return FALSE;
/*
* Add shadows to override redirect windows (e.g., Gtk menus).
* Add shadows to override redirect windows on X11 unless the toolkit
* indicates that it is handling shadows itself (e.g., Gtk menus).
*/
if (priv->window->override_redirect)
if (priv->window->override_redirect &&
!priv->window->has_custom_frame_extents)
return TRUE;
return FALSE;
@@ -1150,7 +1152,7 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
MetaWindowActorPrivate *priv = self->priv;
MetaRectangle window_rect;
meta_window_get_input_rect (priv->window, &window_rect);
meta_window_get_buffer_rect (priv->window, &window_rect);
/* When running as a Wayland compositor we catch size changes when new
* buffers are attached */
@@ -1324,7 +1326,7 @@ meta_window_actor_new (MetaWindow *window)
priv = self->priv;
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
meta_window_actor_sync_updates_frozen (self);
/* If a window doesn't start off with updates frozen, we should
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
@@ -2020,7 +2022,7 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
}
void
static void
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen)
{
@@ -2037,3 +2039,12 @@ meta_window_actor_set_updates_frozen (MetaWindowActor *self,
meta_window_actor_thaw (self);
}
}
void
meta_window_actor_sync_updates_frozen (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window));
}

View File

@@ -1,12 +1,22 @@
pkglibdir=@MUTTER_PLUGIN_DIR@
pkglibdir = $(MUTTER_PLUGIN_DIR)
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
AM_CPPFLAGS = \
$(MUTTER_CFLAGS) \
-I$(top_builddir)/src \
-I$(top_srcdir)/src \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"
default_la_CFLAGS = -fPIC
default_la_SOURCES = default.c
default_la_LDFLAGS = -module -avoid-version -no-undefined
default_la_LIBADD = @CLUTTER_LIBS@
default_la_LIBADD = $(CLUTTER_LIBS)
pkglib_LTLIBRARIES = default.la

View File

@@ -546,6 +546,26 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
return b_area - a_area; /* positive ret value denotes b > a, ... */
}
/* ... and another helper for get_minimal_spanning_set_for_region()... */
static gboolean
check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
{
/* Check whether @strut actually aligns to the side of @rect it claims */
switch (strut->side)
{
case META_SIDE_TOP:
return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
case META_SIDE_BOTTOM:
return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
case META_SIDE_LEFT:
return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
case META_SIDE_RIGHT:
return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
default:
return FALSE;
}
}
/**
* meta_rectangle_get_minimal_spanning_set_for_region:
* @basic_rect: Input rectangle
@@ -630,7 +650,8 @@ meta_rectangle_get_minimal_spanning_set_for_region (
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
GList *rect_iter;
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
MetaStrut *strut = (MetaStrut*)strut_iter->data;
MetaRectangle *strut_rect = &strut->rect;
tmp_list = ret;
ret = NULL;
@@ -638,7 +659,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
while (rect_iter)
{
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
if (!meta_rectangle_overlap (rect, strut_rect))
if (!meta_rectangle_overlap (strut_rect, rect) ||
!check_strut_align (strut, basic_rect))
ret = g_list_prepend (ret, rect);
else
{

View File

@@ -404,31 +404,6 @@ setup_constraint_info (ConstraintInfo *info,
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly - don't get fooled by
* windows which hide their titlebar when maximized or which are
* client decorated; that's not the same as fullscreen, even
* if there are no struts making the workarea smaller than
* the monitor.
*/
if (meta_prefs_get_force_fullscreen() &&
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
!window->hide_titlebar_when_maximized &&
(window->decorated || !meta_window_is_client_decorated (window)) &&
meta_rectangle_equal (new, &monitor_info->rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
{
/*
meta_topic (META_DEBUG_GEOMETRY,
*/
meta_warning (
"Treating resize request of legacy application %s as a "
"fullscreen request\n",
window->desc);
meta_window_make_fullscreen_internal (window);
}
/* Log all this information for debugging */
meta_topic (META_DEBUG_GEOMETRY,
"Setting up constraint info:\n"
@@ -613,7 +588,7 @@ update_onscreen_requirements (MetaWindow *window,
window->require_fully_onscreen =
meta_rectangle_contained_in_region (info->usable_screen_region,
&info->current);
if (old ^ window->require_fully_onscreen)
if (old != window->require_fully_onscreen)
meta_topic (META_DEBUG_GEOMETRY,
"require_fully_onscreen for %s toggled to %s\n",
window->desc,
@@ -626,7 +601,7 @@ update_onscreen_requirements (MetaWindow *window,
window->require_on_single_monitor =
meta_rectangle_contained_in_region (info->usable_monitor_region,
&info->current);
if (old ^ window->require_on_single_monitor)
if (old != window->require_on_single_monitor)
meta_topic (META_DEBUG_GEOMETRY,
"require_on_single_monitor for %s toggled to %s\n",
window->desc,
@@ -645,7 +620,7 @@ update_onscreen_requirements (MetaWindow *window,
window->require_titlebar_visible =
meta_rectangle_overlaps_with_region (info->usable_screen_region,
&titlebar_rect);
if (old ^ window->require_titlebar_visible)
if (old != window->require_titlebar_visible)
meta_topic (META_DEBUG_GEOMETRY,
"require_titlebar_visible for %s toggled to %s\n",
window->desc,

View File

@@ -29,6 +29,9 @@
#include <meta/errors.h>
#include "util-private.h"
#include "x11/window-x11.h"
#include "x11/window-x11-private.h"
/* Looks up the MetaWindow representing the frame of the given X window.
* Used as a helper function by a bunch of the functions below.
*
@@ -69,6 +72,8 @@ meta_core_get (Display *xdisplay,
MetaDisplay *display = meta_display_for_x_display (xdisplay);
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = window_x11->priv;
va_start (args, xwindow);
@@ -103,10 +108,10 @@ meta_core_get (Display *xdisplay,
if (!*((gboolean*)answer)) goto out; /* see above */
break;
case META_CORE_GET_CLIENT_WIDTH:
*((gint*)answer) = window->rect.width;
*((gint*)answer) = priv->client_rect.width;
break;
case META_CORE_GET_CLIENT_HEIGHT:
*((gint*)answer) = window->rect.height;
*((gint*)answer) = priv->client_rect.height;
break;
case META_CORE_GET_FRAME_FLAGS:
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
@@ -120,11 +125,8 @@ meta_core_get (Display *xdisplay,
case META_CORE_GET_ICON:
*((GdkPixbuf**)answer) = window->icon;
break;
case META_CORE_GET_FRAME_WIDTH:
*((gint*)answer) = window->frame->rect.width;
break;
case META_CORE_GET_FRAME_HEIGHT:
*((gint*)answer) = window->frame->rect.height;
case META_CORE_GET_FRAME_RECT:
meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
break;
case META_CORE_GET_THEME_VARIANT:
*((char**)answer) = window->gtk_theme_variant;
@@ -390,6 +392,22 @@ meta_core_show_window_menu (Display *xdisplay,
meta_window_show_menu (window, menu, root_x, root_y);
}
void
meta_core_show_window_menu_for_rect (Display *xdisplay,
Window frame_xwindow,
MetaWindowMenuType menu,
MetaRectangle *rect,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_focus (window, timestamp);
meta_window_show_menu_for_rect (window, menu, rect);
}
const char*
meta_core_get_workspace_name_with_index (Display *xdisplay,
Window xroot,

View File

@@ -26,6 +26,7 @@
/* Don't include core headers here */
#include <gdk/gdkx.h>
#include <meta/common.h>
#include <meta/boxes.h>
typedef enum
{
@@ -37,8 +38,7 @@ typedef enum
META_CORE_GET_FRAME_TYPE,
META_CORE_GET_MINI_ICON,
META_CORE_GET_ICON,
META_CORE_GET_FRAME_WIDTH,
META_CORE_GET_FRAME_HEIGHT,
META_CORE_GET_FRAME_RECT,
META_CORE_GET_THEME_VARIANT,
} MetaCoreGetType;
@@ -139,6 +139,12 @@ void meta_core_show_window_menu (Display *xdisplay,
int root_y,
guint32 timestamp);
void meta_core_show_window_menu_for_rect (Display *xdisplay,
Window frame_xwindow,
MetaWindowMenuType menu,
MetaRectangle *rect,
guint32 timestamp);
gboolean meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,
MetaGrabOp op,

View File

@@ -35,6 +35,7 @@
#include <meta/boxes.h>
#include <meta/display.h>
#include "keybindings-private.h"
#include "gesture-tracker-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
@@ -181,7 +182,6 @@ struct _MetaDisplay
/* current window operation */
MetaGrabOp grab_op;
MetaWindow *grab_window;
Window grab_xwindow;
int grab_button;
int grab_anchor_root_x;
int grab_anchor_root_y;
@@ -254,6 +254,8 @@ struct _MetaDisplay
/* Managed by compositor.c */
MetaCompositor *compositor;
MetaGestureTracker *gesture_tracker;
int composite_event_base;
int composite_error_base;
int composite_major_version;
@@ -443,4 +445,6 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
guint32 *timestamp);
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
#endif

View File

@@ -51,6 +51,8 @@
#include "meta-cursor-tracker-private.h"
#include "meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#include "compositor-private.h"
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
@@ -146,6 +148,11 @@ static void update_window_grab_modifiers (MetaDisplay *display);
static void prefs_changed_callback (MetaPreference pref,
void *data);
static void meta_display_grab_window_touch (MetaDisplay *display,
Window xwindow);
static void meta_display_ungrab_window_touch (MetaDisplay *display,
Window xwindow);
static void
meta_display_get_property(GObject *object,
guint prop_id,
@@ -413,6 +420,28 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
gnome_wm_keybindings = wm_keybindings;
}
static void
gesture_tracker_state_changed (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state,
MetaDisplay *display)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
int event_mode;
if (state == META_SEQUENCE_ACCEPTED)
event_mode = XIAcceptTouch;
else if (state == META_SEQUENCE_REJECTED)
event_mode = XIRejectTouch;
else
return;
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
clutter_x11_event_sequence_get_touch_detail (sequence),
DefaultRootWindow (display->xdisplay), event_mode);
}
/**
* meta_display_open:
*
@@ -805,8 +834,16 @@ meta_display_open (void)
enable_compositor (the_display);
meta_screen_init_workspaces (screen);
meta_screen_create_guard_window (screen);
/* Set up touch support */
the_display->gesture_tracker = meta_gesture_tracker_new (0);
g_signal_connect (the_display->gesture_tracker, "state-changed",
G_CALLBACK (gesture_tracker_state_changed), the_display);
meta_display_grab_window_touch (the_display,
DefaultRootWindow (the_display->xdisplay));
/* We know that if mutter is running as a Wayland compositor,
* we start out with no windows.
*/
@@ -976,6 +1013,10 @@ meta_display_close (MetaDisplay *display,
meta_display_remove_autoraise_callback (display);
meta_display_ungrab_window_touch (display,
DefaultRootWindow (display->xdisplay));
g_clear_object (&display->gesture_tracker);
if (display->focus_timeout_id)
g_source_remove (display->focus_timeout_id);
display->focus_timeout_id = 0;
@@ -1343,23 +1384,7 @@ window_raise_with_delay_callback (void *data)
*/
if (meta_stack_get_top (window->screen->stack) != window)
{
int x, y, root_x, root_y;
Window root, child;
MetaRectangle frame_rect;
unsigned int mask;
gboolean same_screen;
gboolean point_in_window;
meta_error_trap_push (window->display);
same_screen = XQueryPointer (window->display->xdisplay,
window->xwindow,
&root, &child,
&root_x, &root_y, &x, &y, &mask);
meta_error_trap_pop (window->display);
meta_window_get_frame_rect (window, &frame_rect);
point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
if (same_screen && point_in_window)
if (meta_window_has_pointer (window))
meta_window_raise (window);
else
meta_topic (META_DEBUG_FOCUS,
@@ -1367,7 +1392,7 @@ window_raise_with_delay_callback (void *data)
window->desc);
}
return FALSE;
return G_SOURCE_REMOVE;
}
void
@@ -1696,15 +1721,15 @@ meta_display_update_cursor (MetaDisplay *display)
}
static MetaWindow *
get_toplevel_transient_for (MetaWindow *window)
get_first_freefloating_window (MetaWindow *window)
{
while (TRUE)
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (parent == NULL)
return window;
window = parent;
}
while (meta_window_is_attached_dialog (window))
window = meta_window_get_transient_for (window);
/* Attached dialogs should always have a non-NULL transient-for */
g_assert (window != NULL);
return window;
}
gboolean
@@ -1752,11 +1777,11 @@ meta_display_begin_grab_op (MetaDisplay *display,
grab_window = window;
/* If window is a modal dialog attached to its parent,
* grab the parent instead for moving.
/* If we're trying to move a window, move the first
* non-attached dialog instead.
*/
if (meta_window_is_attached_dialog (window) && meta_grab_op_is_moving (op))
grab_window = get_toplevel_transient_for (window);
if (meta_grab_op_is_moving (op))
grab_window = get_first_freefloating_window (window);
g_assert (grab_window != NULL);
g_assert (op != META_GRAB_OP_NONE);
@@ -1826,8 +1851,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
"Grab op %u on window %s successful\n",
display->grab_op, window ? window->desc : "(null)");
meta_window_get_client_root_coords (display->grab_window,
&display->grab_initial_window_pos);
meta_window_get_frame_rect (display->grab_window,
&display->grab_initial_window_pos);
display->grab_anchor_window_pos = display->grab_initial_window_pos;
if (meta_is_wayland_compositor ())
@@ -2070,6 +2095,35 @@ meta_display_ungrab_window_buttons (MetaDisplay *display,
}
}
static void
meta_display_grab_window_touch (MetaDisplay *display,
Window xwindow)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
xwindow, False, &mask, 1, &mods);
}
static void
meta_display_ungrab_window_touch (MetaDisplay *display,
Window xwindow)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
XIGrabModifiers mods = { XIAnyModifier, 0 };
XIUngrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID, xwindow, 1, &mods);
}
/* Grab buttons we only grab while unfocused in click-to-focus mode */
#define MAX_FOCUS_BUTTON 4
void
@@ -2525,21 +2579,19 @@ mru_cmp (gconstpointer a,
* meta_display_get_tab_list:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: (allow-none): origin workspace
* @workspace: (nullable): origin workspace
*
* Determine the list of windows that should be displayed for Alt-TAB
* functionality. The windows are returned in most recently used order.
* If @workspace is not %NULL, the list only conains windows that are on
* @workspace or have the demands-attention hint set; otherwise it contains
* all windows on @screen.
* all windows.
*
* Returns: (transfer container) (element-type Meta.Window): List of windows
*/
GList*
meta_display_get_tab_list (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace)
{
GList *tab_list = NULL;
@@ -2595,7 +2647,7 @@ meta_display_get_tab_list (MetaDisplay *display,
* @display: a #MetaDisplay
* @type: type of tab list
* @workspace: origin workspace
* @window: (allow-none): starting window
* @window: (nullable): starting window
* @backward: If %TRUE, look for the previous window.
*
* Determine the next window that should be displayed for Alt-TAB
@@ -2614,7 +2666,7 @@ meta_display_get_tab_next (MetaDisplay *display,
gboolean skip;
GList *tab_list;
MetaWindow *ret;
tab_list = meta_display_get_tab_list (display, type, NULL, workspace);
tab_list = meta_display_get_tab_list (display, type, workspace);
if (tab_list == NULL)
return NULL;
@@ -3169,3 +3221,9 @@ meta_display_create_x_cursor (MetaDisplay *display,
{
return meta_cursor_create_x_cursor (display->xdisplay, cursor);
}
MetaGestureTracker *
meta_display_get_gesture_tracker (MetaDisplay *display)
{
return display->gesture_tracker;
}

View File

@@ -1134,13 +1134,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
initialize_grab_edge_resistance_data (display);
}
/* Note that old_[xy] and new_[xy] are with respect to inner positions of
* the window.
*/
void
meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
@@ -1153,8 +1148,8 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
meta_window_get_frame_rect (window, &old_outer);
proposed_outer = old_outer;
proposed_outer.x += (*new_x - old_x);
proposed_outer.y += (*new_y - old_y);
proposed_outer.x = *new_x;
proposed_outer.y = *new_y;
new_outer = proposed_outer;
window->display->grab_last_user_action_was_snap = snap;
@@ -1205,26 +1200,20 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
else
smaller_y_change = bottom_change;
*new_x = old_x + smaller_x_change +
*new_x = old_outer.x + smaller_x_change +
(BOX_LEFT (*reference) - BOX_LEFT (old_outer));
*new_y = old_y + smaller_y_change +
*new_y = old_outer.y + smaller_y_change +
(BOX_TOP (*reference) - BOX_TOP (old_outer));
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"outer x & y move-to coordinate changed from %d,%d to %d,%d\n",
proposed_outer.x, proposed_outer.y,
old_outer.x + (*new_x - old_x),
old_outer.y + (*new_y - old_y));
*new_x, *new_y);
}
}
/* Note that old_(width|height) and new_(width|height) are with respect to
* sizes of the inner window.
*/
void
meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
@@ -1237,8 +1226,8 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
gboolean is_resize;
meta_window_get_frame_rect (window, &old_outer);
proposed_outer_width = old_outer.width + (*new_width - old_width);
proposed_outer_height = old_outer.height + (*new_height - old_height);
proposed_outer_width = *new_width;
proposed_outer_height = *new_height;
meta_rectangle_resize_with_gravity (&old_outer,
&new_outer,
gravity,
@@ -1256,8 +1245,8 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
is_keyboard_op,
is_resize))
{
*new_width = old_width + (new_outer.width - old_outer.width);
*new_height = old_height + (new_outer.height - old_outer.height);
*new_width = new_outer.width;
*new_height = new_outer.height;
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"outer width & height got changed from %d,%d to %d,%d\n",

View File

@@ -25,16 +25,12 @@
#include "window-private.h"
void meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op);
void meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,

File diff suppressed because it is too large Load Diff

View File

@@ -29,4 +29,3 @@ void meta_display_init_events (MetaDisplay *display);
void meta_display_free_events (MetaDisplay *display);
#endif

View File

@@ -109,6 +109,19 @@ meta_window_ensure_frame (MetaWindow *window)
XChangeWindowAttributes (window->display->xdisplay,
frame->xwindow, CWEventMask, &attrs);
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISelectEvents (window->display->xdisplay, frame->xwindow, &mask, 1);
}
meta_display_register_x_window (window->display, &frame->xwindow, window);
meta_error_trap_push (window->display);
@@ -121,9 +134,6 @@ meta_window_ensure_frame (MetaWindow *window)
"Incrementing unmaps_pending on %s for reparent\n", window->desc);
window->unmaps_pending += 1;
}
/* window was reparented to this position */
window->rect.x = 0;
window->rect.y = 0;
stack_window.x11.xwindow = window->xwindow;
meta_stack_tracker_record_remove (window->screen->stack_tracker,
@@ -132,8 +142,8 @@ meta_window_ensure_frame (MetaWindow *window)
XReparentWindow (window->display->xdisplay,
window->xwindow,
frame->xwindow,
window->rect.x,
window->rect.y);
frame->child_x,
frame->child_y);
/* FIXME handle this error */
meta_error_trap_pop (window->display);
@@ -202,7 +212,7 @@ meta_window_destroy_frame (MetaWindow *window)
XReparentWindow (window->display->xdisplay,
window->xwindow,
window->screen->xroot,
/* Using anything other than meta_window_get_position()
/* Using anything other than client root window coordinates
* coordinates here means we'll need to ensure a configure
* notify event is sent; see bug 399552.
*/

View File

@@ -0,0 +1,83 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file gesture-tracker-private.h Manages gestures on windows/desktop
*
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
* based on the outcome of those.
*/
/*
* 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_GESTURE_TRACKER_PRIVATE_H
#define META_GESTURE_TRACKER_PRIVATE_H
#include <glib-object.h>
#include <clutter/clutter.h>
#include <meta/window.h>
#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ())
#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker))
#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
#define META_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_GESTURE_TRACKER))
#define META_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_GESTURE_TRACKER))
#define META_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
typedef struct _MetaGestureTracker MetaGestureTracker;
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
typedef enum {
META_SEQUENCE_NONE,
META_SEQUENCE_ACCEPTED,
META_SEQUENCE_REJECTED,
META_SEQUENCE_PENDING_END
} MetaSequenceState;
struct _MetaGestureTracker
{
GObject parent_instance;
};
struct _MetaGestureTrackerClass
{
GObjectClass parent_class;
void (* state_changed) (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state);
};
GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
MetaGestureTracker * meta_gesture_tracker_new (guint autodeny_timeout);
gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
const ClutterEvent *event);
gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state);
MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence);
gboolean meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
const ClutterEvent *event);
#endif /* META_GESTURE_TRACKER_PRIVATE_H */

555
src/core/gesture-tracker.c Normal file
View File

@@ -0,0 +1,555 @@
/*
* 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include "gesture-tracker-private.h"
#include "meta-surface-actor.h"
#define DISTANCE_THRESHOLD 30
typedef struct _MetaGestureTrackerPrivate MetaGestureTrackerPrivate;
typedef struct _GestureActionData GestureActionData;
typedef struct _MetaSequenceInfo MetaSequenceInfo;
struct _MetaSequenceInfo
{
MetaGestureTracker *tracker;
ClutterEventSequence *sequence;
MetaSequenceState state;
guint autodeny_timeout_id;
gfloat start_x;
gfloat start_y;
};
struct _GestureActionData
{
ClutterGestureAction *gesture;
MetaSequenceState state;
guint gesture_begin_id;
guint gesture_end_id;
guint gesture_cancel_id;
};
struct _MetaGestureTrackerPrivate
{
GHashTable *sequences; /* Hashtable of ClutterEventSequence->MetaSequenceInfo */
MetaSequenceState stage_state;
GArray *stage_gestures; /* Array of GestureActionData */
GList *listeners; /* List of ClutterGestureAction */
guint autodeny_timeout;
};
enum {
PROP_AUTODENY_TIMEOUT = 1
};
enum {
STATE_CHANGED,
N_SIGNALS
};
#define DEFAULT_AUTODENY_TIMEOUT 150
static guint signals[N_SIGNALS] = { 0 };
static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
static void
meta_gesture_tracker_finalize (GObject *object)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
g_hash_table_destroy (priv->sequences);
g_array_free (priv->stage_gestures, TRUE);
g_list_free (priv->listeners);
G_OBJECT_CLASS (meta_gesture_tracker_parent_class)->finalize (object);
}
static void
meta_gesture_tracker_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
switch (prop_id)
{
case PROP_AUTODENY_TIMEOUT:
priv->autodeny_timeout = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_gesture_tracker_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
switch (prop_id)
{
case PROP_AUTODENY_TIMEOUT:
g_value_set_uint (value, priv->autodeny_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_gesture_tracker_finalize;
object_class->set_property = meta_gesture_tracker_set_property;
object_class->get_property = meta_gesture_tracker_get_property;
g_object_class_install_property (object_class,
PROP_AUTODENY_TIMEOUT,
g_param_spec_uint ("autodeny-timeout",
"Auto-deny timeout",
"Auto-deny timeout",
0, G_MAXUINT, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[STATE_CHANGED] =
g_signal_new ("state-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MetaGestureTrackerClass, state_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
}
static gboolean
autodeny_sequence (gpointer user_data)
{
MetaSequenceInfo *info = user_data;
/* Deny the sequence automatically after the given timeout */
if (info->state == META_SEQUENCE_NONE)
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
META_SEQUENCE_REJECTED);
info->autodeny_timeout_id = 0;
return G_SOURCE_REMOVE;
}
static MetaSequenceInfo *
meta_sequence_info_new (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
MetaGestureTrackerPrivate *priv;
MetaSequenceInfo *info;
guint ms;
priv = meta_gesture_tracker_get_instance_private (tracker);
ms = (priv->autodeny_timeout) ?
priv->autodeny_timeout : DEFAULT_AUTODENY_TIMEOUT;
info = g_slice_new0 (MetaSequenceInfo);
info->tracker = tracker;
info->sequence = event->touch.sequence;
info->state = META_SEQUENCE_NONE;
info->autodeny_timeout_id = g_timeout_add (ms, autodeny_sequence, info);
clutter_event_get_coords (event, &info->start_x, &info->start_y);
return info;
}
static void
meta_sequence_info_free (MetaSequenceInfo *info)
{
if (info->autodeny_timeout_id)
g_source_remove (info->autodeny_timeout_id);
if (info->state == META_SEQUENCE_NONE)
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
META_SEQUENCE_REJECTED);
g_slice_free (MetaSequenceInfo, info);
}
static gboolean
state_is_applicable (MetaSequenceState prev_state,
MetaSequenceState state)
{
if (prev_state == META_SEQUENCE_PENDING_END)
return FALSE;
/* Don't allow reverting to none */
if (state == META_SEQUENCE_NONE)
return FALSE;
/* PENDING_END state is final */
if (prev_state == META_SEQUENCE_PENDING_END)
return FALSE;
/* Sequences must be accepted/denied before PENDING_END */
if (prev_state == META_SEQUENCE_NONE &&
state == META_SEQUENCE_PENDING_END)
return FALSE;
/* Make sequences stick to their accepted/denied state */
if (state != META_SEQUENCE_PENDING_END &&
prev_state != META_SEQUENCE_NONE)
return FALSE;
return TRUE;
}
static gboolean
meta_gesture_tracker_set_state (MetaGestureTracker *tracker,
MetaSequenceState state)
{
MetaGestureTrackerPrivate *priv;
ClutterEventSequence *sequence;
GHashTableIter iter;
priv = meta_gesture_tracker_get_instance_private (tracker);
if (priv->stage_state != state &&
!state_is_applicable (priv->stage_state, state))
return FALSE;
g_hash_table_iter_init (&iter, priv->sequences);
priv->stage_state = state;
while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, NULL))
meta_gesture_tracker_set_sequence_state (tracker, sequence, state);
return TRUE;
}
static gboolean
gesture_begin_cb (ClutterGestureAction *gesture,
ClutterActor *actor,
MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
if (!g_list_find (priv->listeners, gesture) &&
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_ACCEPTED))
priv->listeners = g_list_prepend (priv->listeners, gesture);
return TRUE;
}
static void
gesture_end_cb (ClutterGestureAction *gesture,
ClutterActor *actor,
MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
priv->listeners = g_list_remove (priv->listeners, gesture);
if (!priv->listeners)
meta_gesture_tracker_untrack_stage (tracker);
}
static void
gesture_cancel_cb (ClutterGestureAction *gesture,
ClutterActor *actor,
MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
if (g_list_find (priv->listeners, gesture))
{
priv->listeners = g_list_remove (priv->listeners, gesture);
if (!priv->listeners)
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_PENDING_END);
}
}
static gboolean
cancel_and_unref_gesture_cb (ClutterGestureAction *action)
{
clutter_gesture_action_cancel (action);
g_object_unref (action);
return G_SOURCE_REMOVE;
}
static void
clear_gesture_data (GestureActionData *data)
{
g_signal_handler_disconnect (data->gesture, data->gesture_begin_id);
g_signal_handler_disconnect (data->gesture, data->gesture_end_id);
g_signal_handler_disconnect (data->gesture, data->gesture_cancel_id);
/* Defer cancellation to an idle, as it may happen within event handling */
g_idle_add ((GSourceFunc) cancel_and_unref_gesture_cb, data->gesture);
}
static void
meta_gesture_tracker_init (MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
priv->sequences = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) meta_sequence_info_free);
priv->stage_gestures = g_array_new (FALSE, FALSE, sizeof (GestureActionData));
g_array_set_clear_func (priv->stage_gestures, (GDestroyNotify) clear_gesture_data);
}
MetaGestureTracker *
meta_gesture_tracker_new (guint autodeny_timeout)
{
return g_object_new (META_TYPE_GESTURE_TRACKER,
"autodeny-timeout", autodeny_timeout,
NULL);
}
static void
meta_gesture_tracker_track_stage (MetaGestureTracker *tracker,
ClutterActor *stage)
{
MetaGestureTrackerPrivate *priv;
GList *actions, *l;
priv = meta_gesture_tracker_get_instance_private (tracker);
actions = clutter_actor_get_actions (stage);
for (l = actions; l; l = l->next)
{
GestureActionData data;
if (!CLUTTER_IS_GESTURE_ACTION (l->data))
continue;
data.gesture = g_object_ref (l->data);
data.state = META_SEQUENCE_NONE;
data.gesture_begin_id =
g_signal_connect (data.gesture, "gesture-begin",
G_CALLBACK (gesture_begin_cb), tracker);
data.gesture_end_id =
g_signal_connect (data.gesture, "gesture-end",
G_CALLBACK (gesture_end_cb), tracker);
data.gesture_cancel_id =
g_signal_connect (data.gesture, "gesture-cancel",
G_CALLBACK (gesture_cancel_cb), tracker);
g_array_append_val (priv->stage_gestures, data);
}
g_list_free (actions);
}
static void
meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
priv->stage_state = META_SEQUENCE_NONE;
g_hash_table_remove_all (priv->sequences);
if (priv->stage_gestures->len > 0)
g_array_remove_range (priv->stage_gestures, 0, priv->stage_gestures->len);
g_list_free (priv->listeners);
priv->listeners = NULL;
}
gboolean
meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
MetaGestureTrackerPrivate *priv;
ClutterEventSequence *sequence;
MetaSequenceInfo *info;
ClutterActor *stage;
gfloat x, y;
sequence = clutter_event_get_event_sequence (event);
if (!sequence)
return FALSE;
priv = meta_gesture_tracker_get_instance_private (tracker);
stage = CLUTTER_ACTOR (clutter_event_get_stage (event));
switch (event->type)
{
case CLUTTER_TOUCH_BEGIN:
if (g_hash_table_size (priv->sequences) == 0)
meta_gesture_tracker_track_stage (tracker, stage);
info = meta_sequence_info_new (tracker, event);
g_hash_table_insert (priv->sequences, sequence, info);
if (priv->stage_gestures->len == 0)
{
/* If no gestures are attached, reject the sequence right away */
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
}
else if (priv->stage_state != META_SEQUENCE_NONE)
{
/* Make the sequence state match the general state */
meta_gesture_tracker_set_sequence_state (tracker, sequence,
priv->stage_state);
}
break;
case CLUTTER_TOUCH_END:
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return FALSE;
/* If nothing was done yet about the sequence, reject it so X11
* clients may see it
*/
if (info->state == META_SEQUENCE_NONE)
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
g_hash_table_remove (priv->sequences, sequence);
if (g_hash_table_size (priv->sequences) == 0)
meta_gesture_tracker_untrack_stage (tracker);
break;
case CLUTTER_TOUCH_UPDATE:
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return FALSE;
clutter_event_get_coords (event, &x, &y);
if (info->state == META_SEQUENCE_NONE &&
(ABS (info->start_x - x) > DISTANCE_THRESHOLD ||
ABS (info->start_y - y) > DISTANCE_THRESHOLD))
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
break;
default:
return FALSE;
break;
}
return TRUE;
}
gboolean
meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state)
{
MetaGestureTrackerPrivate *priv;
MetaSequenceInfo *info;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
priv = meta_gesture_tracker_get_instance_private (tracker);
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return FALSE;
else if (state == info->state)
return TRUE;
if (!state_is_applicable (info->state, state))
return FALSE;
/* Unset autodeny timeout */
if (info->autodeny_timeout_id)
{
g_source_remove (info->autodeny_timeout_id);
info->autodeny_timeout_id = 0;
}
info->state = state;
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
/* If the sequence was denied, set immediately to PENDING_END after emission */
if (state == META_SEQUENCE_REJECTED)
{
info->state = META_SEQUENCE_PENDING_END;
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
}
return TRUE;
}
MetaSequenceState
meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence)
{
MetaGestureTrackerPrivate *priv;
MetaSequenceInfo *info;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), META_SEQUENCE_PENDING_END);
priv = meta_gesture_tracker_get_instance_private (tracker);
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return META_SEQUENCE_PENDING_END;
return info->state;
}
gboolean
meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
MetaSequenceState state;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
sequence = clutter_event_get_event_sequence (event);
if (!sequence)
return FALSE;
state = meta_gesture_tracker_get_sequence_state (tracker, sequence);
return (event->type != CLUTTER_TOUCH_END &&
(state == META_SEQUENCE_REJECTED || state == META_SEQUENCE_PENDING_END));
}

View File

@@ -57,7 +57,11 @@
#include "wayland/meta-wayland.h"
#include "backends/x11/meta-backend-x11.h"
#include "x11/window-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
@@ -1220,7 +1224,7 @@ meta_window_grab_keys (MetaWindow *window)
}
meta_window_change_keygrabs (window,
meta_window_get_toplevel_xwindow (window),
meta_window_x11_get_toplevel_xwindow (window),
TRUE);
window->keys_grabbed = TRUE;
@@ -1434,7 +1438,7 @@ meta_window_grab_all_keys (MetaWindow *window,
window->desc);
meta_window_focus (window, timestamp);
grabwindow = meta_window_get_toplevel_xwindow (window);
grabwindow = meta_window_x11_get_toplevel_xwindow (window);
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
@@ -1906,12 +1910,12 @@ process_mouse_move_resize_grab (MetaDisplay *display,
else if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else
meta_window_move_resize (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
meta_window_move_resize_frame (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
/* End grab */
return FALSE;
@@ -1927,6 +1931,7 @@ process_keyboard_move_grab (MetaDisplay *display,
ClutterKeyEvent *event)
{
gboolean handled;
MetaRectangle frame_rect;
int x, y;
int incr;
gboolean smart_snap;
@@ -1941,7 +1946,9 @@ process_keyboard_move_grab (MetaDisplay *display,
if (is_modifier (event->keyval))
return TRUE;
meta_window_get_position (window, &x, &y);
meta_window_get_frame_rect (window, &frame_rect);
x = frame_rect.x;
y = frame_rect.y;
smart_snap = (event->modifier_state & CLUTTER_SHIFT_MASK) != 0;
@@ -1965,12 +1972,12 @@ process_keyboard_move_grab (MetaDisplay *display,
if (window->shaken_loose)
meta_window_maximize (window, META_MAXIMIZE_BOTH);
else
meta_window_move_resize (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
meta_window_move_resize_frame (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
}
/* When moving by increments, we still snap to edges if the move
@@ -2016,23 +2023,18 @@ process_keyboard_move_grab (MetaDisplay *display,
if (handled)
{
MetaRectangle old_rect;
meta_topic (META_DEBUG_KEYBINDINGS,
"Computed new window location %d,%d due to keypress\n",
x, y);
meta_window_get_client_root_coords (window, &old_rect);
meta_window_edge_resistance_for_move (window,
old_rect.x,
old_rect.y,
&x,
&y,
NULL,
smart_snap,
TRUE);
meta_window_move (window, TRUE, x, y);
meta_window_move_frame (window, TRUE, x, y);
meta_window_update_keyboard_move (window);
}
@@ -2166,6 +2168,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
MetaWindow *window,
ClutterKeyEvent *event)
{
MetaRectangle frame_rect;
gboolean handled;
int height_inc;
int width_inc;
@@ -2186,12 +2189,12 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (event->keyval == CLUTTER_KEY_Escape)
{
/* End resize and restore to original state. */
meta_window_move_resize (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
meta_window_move_resize_frame (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
return FALSE;
}
@@ -2202,6 +2205,10 @@ process_keyboard_resize_grab (MetaDisplay *display,
width = window->rect.width;
height = window->rect.height;
meta_window_get_frame_rect (window, &frame_rect);
width = frame_rect.width;
height = frame_rect.height;
gravity = meta_resize_gravity_from_grab_op (display->grab_op);
smart_snap = (event->modifier_state & CLUTTER_SHIFT_MASK) != 0;
@@ -2359,18 +2366,13 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (handled)
{
MetaRectangle old_rect;
meta_topic (META_DEBUG_KEYBINDINGS,
"Computed new window size due to keypress: "
"%dx%d, gravity %s\n",
width, height, meta_gravity_to_string (gravity));
old_rect = window->rect; /* Don't actually care about x,y */
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_resize (window,
old_rect.width,
old_rect.height,
&width,
&height,
gravity,
@@ -2378,15 +2380,11 @@ process_keyboard_resize_grab (MetaDisplay *display,
smart_snap,
TRUE);
/* We don't need to update unless the specified width and height
* are actually different from what we had before.
*/
if (window->rect.width != width || window->rect.height != height)
meta_window_resize_with_gravity (window,
TRUE,
width,
height,
gravity);
meta_window_resize_frame_with_gravity (window,
TRUE,
width,
height,
gravity);
meta_window_update_keyboard_resize (window, FALSE);
}
@@ -3172,6 +3170,7 @@ handle_set_spew_mark (MetaDisplay *display,
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
#ifdef HAVE_NATIVE_BACKEND
static void
handle_switch_vt (MetaDisplay *display,
MetaScreen *screen,
@@ -3189,11 +3188,12 @@ handle_switch_vt (MetaDisplay *display,
g_error_free (error);
}
}
#endif /* HAVE_NATIVE_BACKEND */
/**
* meta_keybindings_set_custom_handler:
* @name: The name of the keybinding to set
* @handler: (allow-none): The new handler function
* @handler: (nullable): The new handler function
* @user_data: User data to pass to the callback
* @free_data: Will be called when this handler is overridden.
*
@@ -3481,7 +3481,9 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_SET_SPEW_MARK,
handle_set_spew_mark, 0);
if (meta_is_wayland_compositor ())
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_NATIVE (backend))
{
add_builtin_keybinding (display,
"switch-to-session-1",
@@ -3532,6 +3534,7 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 7);
}
#endif /* HAVE_NATIVE_BACKEND */
#undef REVERSES_AND_REVERSED

View File

@@ -181,7 +181,9 @@ static gboolean opt_replace_wm;
static gboolean opt_disable_sm;
static gboolean opt_sync;
static gboolean opt_wayland;
#ifdef HAVE_NATIVE_BACKEND
static gboolean opt_display_server;
#endif
static GOptionEntry meta_options[] = {
{
@@ -225,11 +227,13 @@ static GOptionEntry meta_options[] = {
N_("Run as a wayland compositor"),
NULL
},
#ifdef HAVE_NATIVE_BACKEND
{
"display-server", 0, 0, G_OPTION_ARG_NONE,
&opt_display_server,
N_("Run as a full display server, rather than nested")
},
#endif
{NULL}
};
@@ -332,8 +336,10 @@ meta_init (void)
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (opt_display_server)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
#endif
meta_set_is_wayland_compositor (opt_wayland);

View File

@@ -515,85 +515,84 @@ find_first_fit (MetaWindow *window,
meta_window_get_frame_rect (window, &rect);
#ifdef WITH_VERBOSE_MODE
{
char monitor_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
monitor_location_string);
meta_topic (META_DEBUG_XINERAMA,
"Natural monitor is %s\n",
monitor_location_string);
}
{
char monitor_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
monitor_location_string);
meta_topic (META_DEBUG_XINERAMA,
"Natural monitor is %s\n",
monitor_location_string);
}
#endif
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
center_tile_rect_in_area (&rect, &work_area);
center_tile_rect_in_area (&rect, &work_area);
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, windows))
{
*new_x = rect.x;
*new_y = rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, windows))
{
*new_x = rect.x;
*new_y = rect.y;
retval = TRUE;
retval = TRUE;
goto out;
}
goto out;
}
/* try below each window */
tmp = below_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
/* try below each window */
tmp = below_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
meta_window_get_frame_rect (w, &frame_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = frame_rect.x;
rect.y = frame_rect.y + frame_rect.height;
rect.x = frame_rect.x;
rect.y = frame_rect.y + frame_rect.height;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, below_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, below_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
retval = TRUE;
retval = TRUE;
goto out;
}
goto out;
}
tmp = tmp->next;
}
tmp = tmp->next;
}
/* try to the right of each window */
tmp = right_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
/* try to the right of each window */
tmp = right_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
meta_window_get_frame_rect (w, &frame_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = frame_rect.x + frame_rect.width;
rect.y = frame_rect.y;
rect.x = frame_rect.x + frame_rect.width;
rect.y = frame_rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, right_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, right_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
retval = TRUE;
retval = TRUE;
goto out;
}
goto out;
}
tmp = tmp->next;
}
tmp = tmp->next;
}
out:
g_list_free (below_sorted);
g_list_free (right_sorted);
return retval;

View File

@@ -180,7 +180,7 @@ typedef struct
/**
* MetaStringPreference:
* @handler: (allow-none): A handler. Many of the string preferences
* @handler: (nullable): A handler. Many of the string preferences
* aren't stored as strings and need parsing; others of them have
* default values which can't be solved in the general case. If you
* include a function pointer here, it will be called instead of writing
@@ -192,7 +192,7 @@ typedef struct
* in particular the @result (out) parameter as returned by
* g_settings_get_mapped() will be ignored in all cases.
* This may be %NULL. If it is, see "target", below.
* @target: (allow-none): Where to write the incoming string.
* @target: (nullable): Where to write the incoming string.
* This must be %NULL if the handler is non-%NULL.
* If the incoming string is %NULL, no change will be made.
*/
@@ -1234,6 +1234,7 @@ xsettings_overrides_changed (GSettings *settings,
GVariant *value;
GVariantDict overrides;
int shell_shows_app_menu = 1;
gboolean changed = FALSE;
if (!g_settings_get_boolean (settings, "active"))
goto out;
@@ -1247,8 +1248,13 @@ xsettings_overrides_changed (GSettings *settings,
"Gtk/ShellShowsAppMenu", "i", &shell_shows_app_menu);
g_variant_dict_clear (&overrides);
changed = (show_fallback_app_menu == !!shell_shows_app_menu);
out:
show_fallback_app_menu = !shell_shows_app_menu;
if (changed)
queue_changed (META_PREF_BUTTON_LAYOUT);
}
/**

View File

@@ -135,6 +135,7 @@ MetaScreen* meta_screen_new (MetaDisplay *displ
guint32 timestamp);
void meta_screen_free (MetaScreen *screen,
guint32 timestamp);
void meta_screen_init_workspaces (MetaScreen *screen);
void meta_screen_manage_all_windows (MetaScreen *screen);
void meta_screen_foreach_window (MetaScreen *screen,
MetaScreenWindowFunc func,

View File

@@ -506,7 +506,6 @@ meta_screen_new (MetaDisplay *display,
Atom wm_sn_atom;
char buf[128];
guint32 manager_timestamp;
gulong current_workspace;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@@ -721,24 +720,10 @@ meta_screen_new (MetaDisplay *display,
meta_screen_update_workspace_layout (screen);
/* Get current workspace */
current_workspace = 0;
if (meta_prop_get_cardinal (screen->display,
screen->xroot,
screen->display->atom__NET_CURRENT_DESKTOP,
&current_workspace))
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
(int) current_workspace);
else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
/* Screens must have at least one workspace at all times,
* so create that required workspace.
*/
meta_workspace_activate (meta_workspace_new (screen), timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
meta_workspace_new (screen);
screen->keys_grabbed = FALSE;
meta_screen_grab_keys (screen);
@@ -764,23 +749,46 @@ meta_screen_new (MetaDisplay *display,
screen->startup_sequence_timeout = 0;
#endif
/* Switch to the _NET_CURRENT_DESKTOP workspace */
{
MetaWorkspace *space;
space = meta_screen_get_workspace_by_index (screen,
current_workspace);
if (space != NULL)
meta_workspace_activate (space, timestamp);
}
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
return screen;
}
void
meta_screen_init_workspaces (MetaScreen *screen)
{
MetaWorkspace *current_workspace;
gulong current_workspace_index = 0;
guint32 timestamp;
g_return_if_fail (META_IS_SCREEN (screen));
timestamp = screen->wm_sn_timestamp;
/* Get current workspace */
if (meta_prop_get_cardinal (screen->display,
screen->xroot,
screen->display->atom__NET_CURRENT_DESKTOP,
&current_workspace_index))
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
(int) current_workspace_index);
else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
meta_workspace_activate (screen->workspaces->data, timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
/* Switch to the _NET_CURRENT_DESKTOP workspace */
current_workspace = meta_screen_get_workspace_by_index (screen,
current_workspace_index);
if (current_workspace != NULL)
meta_workspace_activate (current_workspace, timestamp);
}
void
meta_screen_free (MetaScreen *screen,
guint32 timestamp)

View File

@@ -25,6 +25,7 @@
#include <stdio.h>
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
#include <time.h> /* To initialize random seed */
#include <math.h>
#define NUM_RANDOM_RUNS 10000
@@ -238,7 +239,7 @@ static GSList*
get_strut_list (int which)
{
GSList *ans;
MetaDirection wc = 0; /* wc == who cares? ;-) */
MetaSide wc = 0; /* wc == who cares? ;-) */
ans = NULL;
@@ -248,32 +249,32 @@ get_strut_list (int which)
case 0:
break;
case 1:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, META_SIDE_BOTTOM));
break;
case 2:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_BOTTOM));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, META_SIDE_BOTTOM));
break;
case 3:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_LEFT));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, META_SIDE_BOTTOM));
ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc));
break;
case 4:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP));
break;
case 5:
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, META_SIDE_RIGHT));
break;
case 6:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
break;
}
@@ -623,15 +624,9 @@ test_regions_okay ()
/*************************************************************/
region = get_screen_region (3);
tmp = NULL;
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 675, 420, 525)); /* 220500 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); /* 354000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 320, 1180)); /* 377600 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 800, 475)); /* 380000 */
tmp = g_list_prepend (tmp, new_meta_rect (1200, 20, 400, 1180)); /* 472000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 1600, 425)); /* 680000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 900, 20, 700, 1080)); /* 756000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 700, 1130)); /* 791000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 505)); /* 808000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 1220, 1180)); /* 377600 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1130)); /* 791000 */
#if 0
printf ("Got to here...\n");
char region_list[(RECT_LENGTH+2) * g_list_length (region)];
@@ -1332,6 +1327,7 @@ test_gravity_resize ()
printf ("%s passed.\n", G_STRFUNC);
}
#define EPSILON 0.000000001
static void
test_find_closest_point_to_line ()
{
@@ -1346,7 +1342,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
/* Special test for x1 == x2, so that slop of line is infinite */
x1 = 3.0; y1 = 49.0;
@@ -1357,7 +1353,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
/* Special test for y1 == y2, so perp line has slope of infinity */
x1 = 3.14; y1 = 7.0;
@@ -1368,7 +1364,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
/* Test when we the point we want to be closest to is actually on the line */
x1 = 3.0; y1 = 49.0;
@@ -1379,7 +1375,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
printf ("%s passed.\n", G_STRFUNC);
}

View File

@@ -166,6 +166,7 @@ struct _MetaWindow
* that to toggle between normal/tiled or maximized/tiled states. */
guint saved_maximize : 1;
int tile_monitor_number;
int preferred_output_id;
/* Whether we're shaded */
guint shaded : 1;
@@ -357,7 +358,8 @@ struct _MetaWindow
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
/* if non-NULL, the bounding shape region of the window */
/* if non-NULL, the bounding shape region of the window. Relative to
* the server-side client window. */
cairo_region_t *shape_region;
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
@@ -403,32 +405,32 @@ struct _MetaWindow
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
/* The size we set the window to last (i.e. what we believe
* to be its actual size on the server). The x, y are
* the actual server-side x,y so are relative to the frame
* (meaning that they just hold the frame width and height)
* or the root window (meaning they specify the location
* of the top left of the inner window) as appropriate.
*/
/* The rectangles here are in "frame rect" coordinates. See the
* comment at the top of meta_window_move_resize_internal() for more
* information. */
/* The current window geometry of the window. */
MetaRectangle rect;
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size
* of the client window (i.e. ignoring the frame).
*/
/* The geometry to restore when we unmaximize. */
MetaRectangle saved_rect;
/* This is the geometry the window will have if no constraints have
* applied. We use this whenever we are moving implicitly (for example,
* if we move to avoid a panel, we can snap back to this position if
* the panel moves again). Note that this gives the position and size
* of the client window (i.e. ignoring the frame).
*
* Position always in root coords, unlike window->rect.
* the panel moves again).
*/
MetaRectangle unconstrained_rect;
/* The rectangle of the "server-side" geometry of the buffer,
* in root coordinates.
*
* For X11 windows, this matches XGetGeometry of the toplevel.
*
* For Wayland windows, this matches the buffer size and where
* the surface actor is positioned. */
MetaRectangle buffer_rect;
/* Cached net_wm_icon_geometry */
MetaRectangle icon_geometry;
@@ -539,23 +541,12 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right);
void meta_window_resize_frame_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw);
void meta_window_move_resize (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw,
int w,
int h);
void meta_window_resize_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity);
void meta_window_change_workspace (MetaWindow *window,
MetaWorkspace *workspace);
@@ -564,17 +555,6 @@ gboolean meta_window_should_be_showing (MetaWindow *window);
void meta_window_update_struts (MetaWindow *window);
/* this gets root coords */
void meta_window_get_position (MetaWindow *window,
int *x,
int *y);
/* Gets root coords for x, y, width & height of client window; uses
* meta_window_get_position for x & y.
*/
void meta_window_get_client_root_coords (MetaWindow *window,
MetaRectangle *rect);
/* gets position we need to set to stay in current position,
* assuming position will be gravity-compensated. i.e.
* this is the position a client would send in a configure
@@ -605,6 +585,10 @@ void meta_window_show_menu (MetaWindow *window,
int x,
int y);
void meta_window_show_menu_for_rect (MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
gboolean meta_window_handle_mouse_grab_op_event (MetaWindow *window,
const ClutterEvent *event);
@@ -694,8 +678,6 @@ gboolean meta_window_handle_ungrabbed_event (MetaWindow *window,
void meta_window_set_surface_mapped (MetaWindow *window,
gboolean surface_mapped);
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_get_titlebar_rect (MetaWindow *window,
@@ -708,7 +690,8 @@ void meta_window_activate_full (MetaWindow *window,
gboolean meta_window_is_client_decorated (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window,
gboolean user_op);
void meta_window_set_urgent (MetaWindow *window,
gboolean urgent);
@@ -721,11 +704,13 @@ void meta_window_update_resize (MetaWindow *window,
void meta_window_move_resize_internal (MetaWindow *window,
MetaMoveResizeFlags flags,
int gravity,
MetaRectangle client_rect);
MetaRectangle frame_rect);
void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op);
void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);
void meta_window_set_alive (MetaWindow *window, gboolean is_alive);
gboolean meta_window_has_pointer (MetaWindow *window);
#endif

View File

@@ -965,6 +965,7 @@ _meta_window_shared_new (MetaDisplay *display,
window->compositor_private = NULL;
window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
window->preferred_output_id = window->monitor->output_id;
window->tile_match = NULL;
@@ -1044,9 +1045,6 @@ _meta_window_shared_new (MetaDisplay *display,
if (window->attached)
meta_window_recalc_features (window);
if (window->decorated)
meta_window_ensure_frame (window);
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK)
{
@@ -1278,6 +1276,12 @@ meta_window_unmanage (MetaWindow *window,
g_list_free (attached_children);
}
/* Make sure to only show window on all workspaces if requested, to
* not confuse other window managers that may take over
*/
if (window->screen->closing && meta_prefs_get_workspaces_only_on_primary ())
meta_window_update_on_all_workspaces (window);
if (window->fullscreen)
{
MetaGroup *group;
@@ -1393,9 +1397,6 @@ meta_window_unmanage (MetaWindow *window,
META_WINDOW_GET_CLASS (window)->unmanage (window);
if (window->frame)
meta_window_destroy_frame (window);
meta_prefs_remove_listener (prefs_changed_callback, window);
meta_screen_queue_check_fullscreen (window->screen);
@@ -1411,6 +1412,7 @@ should_be_on_all_workspaces (MetaWindow *window)
window->on_all_workspaces_requested ||
window->override_redirect ||
(meta_prefs_get_workspaces_only_on_primary () &&
!window->unmanaging &&
!meta_window_is_on_primary_monitor (window));
}
@@ -2654,15 +2656,11 @@ meta_window_save_rect (MetaWindow *window)
{
window->saved_rect.x = window->rect.x;
window->saved_rect.width = window->rect.width;
if (window->frame)
window->saved_rect.x += window->frame->rect.x;
}
if (!window->maximized_vertically)
{
window->saved_rect.y = window->rect.y;
window->saved_rect.height = window->rect.height;
if (window->frame)
window->saved_rect.y += window->frame->rect.y;
}
}
}
@@ -3016,12 +3014,12 @@ unmaximize_window_before_freeing (MetaWindow *window)
* Moreover, it will need to know the unmaximized geometry,
* therefore move_resize the window to saved_rect here
* before closing it. */
meta_window_move_resize (window,
FALSE,
window->saved_rect.x,
window->saved_rect.y,
window->saved_rect.width,
window->saved_rect.height);
meta_window_move_resize_frame (window,
FALSE,
window->saved_rect.x,
window->saved_rect.y,
window->saved_rect.width,
window->saved_rect.height);
}
}
@@ -3078,7 +3076,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
/* Unmaximize to the saved_rect position in the direction(s)
* being unmaximized.
*/
meta_window_get_client_root_coords (window, &target_rect);
target_rect = old_rect;
/* Avoid unmaximizing to "almost maximized" size when the previous size
* is greater then 80% of the work area use MAX_UNMAXIMIZED_WINDOW_AREA of the work area as upper limit
@@ -3115,7 +3113,9 @@ meta_window_unmaximize_internal (MetaWindow *window,
/* Window's size hints may have changed while maximized, making
* saved_rect invalid. #329152
*/
meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect);
ensure_size_hints_satisfied (&target_rect, &window->size_hints);
meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
meta_window_move_resize_internal (window,
META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION,
@@ -3176,7 +3176,6 @@ meta_window_unmaximize_with_gravity (MetaWindow *window,
{
MetaRectangle desired_rect;
meta_window_get_position (window, &desired_rect.x, &desired_rect.y);
desired_rect.width = new_width;
desired_rect.height = new_height;
@@ -3293,12 +3292,12 @@ meta_window_unmake_fullscreen (MetaWindow *window)
meta_window_recalc_features (window);
set_net_wm_state (window);
meta_window_move_resize (window,
FALSE,
target_rect.x,
target_rect.y,
target_rect.width,
target_rect.height);
meta_window_move_resize_frame (window,
FALSE,
target_rect.x,
target_rect.y,
target_rect.width,
target_rect.height);
meta_window_update_layer (window);
@@ -3532,7 +3531,7 @@ maybe_move_attached_dialog (MetaWindow *window,
{
if (meta_window_is_attached_dialog (window))
/* It ignores x,y for such a dialog */
meta_window_move (window, FALSE, 0, 0);
meta_window_move_frame (window, FALSE, 0, 0);
return FALSE;
}
@@ -3551,40 +3550,51 @@ meta_window_get_monitor (MetaWindow *window)
return window->monitor->number;
}
static MetaMonitorInfo *
find_monitor_by_id (MetaWindow *window,
guint id)
{
int i;
for (i = 0; i < window->screen->n_monitor_infos; i++)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
if (info->output_id != 0 && info->output_id == id)
return info;
}
return NULL;
}
/* This is called when the monitor setup has changed. The window->monitor
* reference is still "valid", but refer to the previous monitor setup */
void
meta_window_update_for_monitors_changed (MetaWindow *window)
{
const MetaMonitorInfo *old, *new;
int i;
if (window->type == META_WINDOW_DESKTOP)
return;
if (window->override_redirect)
{
meta_window_update_monitor (window);
meta_window_update_monitor (window, FALSE);
return;
}
old = window->monitor;
/* Start on primary */
new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
/* Try the preferred output first */
new = find_monitor_by_id (window, window->preferred_output_id);
/* But, if we can find the old output on a new monitor, use that */
for (i = 0; i < window->screen->n_monitor_infos; i++)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
/* Otherwise, try to find the old output on a new monitor */
if (!new)
new = find_monitor_by_id (window, old->output_id);
if (info->output_id != 0 &&
info->output_id == old->output_id)
{
new = info;
break;
}
}
/* Fall back to primary if everything else failed */
if (!new)
new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = new->number;
@@ -3602,7 +3612,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
}
void
meta_window_update_monitor (MetaWindow *window)
meta_window_update_monitor (MetaWindow *window,
gboolean user_op)
{
const MetaMonitorInfo *old;
@@ -3612,22 +3623,17 @@ meta_window_update_monitor (MetaWindow *window)
{
meta_window_update_on_all_workspaces (window);
/* If workspaces only on primary and we moved back to primary, ensure that the
* window is now in that workspace. We do this because while the window is on a
* non-primary monitor it is always visible, so it would be very jarring if it
* disappeared when it crossed the monitor border.
/* If workspaces only on primary and we moved back to primary due to a user action,
* ensure that the window is now in that workspace. We do this because while
* the window is on a non-primary monitor it is always visible, so it would be
* very jarring if it disappeared when it crossed the monitor border.
* The one time we want it to both change to the primary monitor and a non-active
* workspace is when dropping the window on some other workspace thumbnail directly.
* That should be handled by explicitly moving the window before changing the
* workspace
* Don't do this if old == NULL, because thats what happens when starting up, and
* we don't want to move all windows around from a previous WM instance. Nor do
* we want it when moving from one primary monitor to another (can happen during
* screen reconfiguration.
* workspace.
*/
if (meta_prefs_get_workspaces_only_on_primary () &&
if (meta_prefs_get_workspaces_only_on_primary () && user_op &&
meta_window_is_on_primary_monitor (window) &&
old != NULL && !old->is_primary &&
window->screen->active_workspace != window->workspace)
meta_window_change_workspace (window, window->screen->active_workspace);
@@ -3638,6 +3644,7 @@ meta_window_update_monitor (MetaWindow *window)
/* If we're changing monitors, we need to update the has_maximize_func flag,
* as the working area has changed. */
meta_window_recalc_features (window);
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
}
}
@@ -3645,14 +3652,29 @@ void
meta_window_move_resize_internal (MetaWindow *window,
MetaMoveResizeFlags flags,
int gravity,
MetaRectangle client_rect)
MetaRectangle frame_rect)
{
/* The rectangle here that's passed in is always the root position
* of the client window. For undecorated or client-decorated windows,
* this is the root position of the X11 window. For server-decorated
* windows, this is the root position of the client area of the window.
/* The rectangle here that's passed in *always* in "frame rect"
* coordinates. That means the position of the frame's visible bounds,
* with x and y being absolute (root window) coordinates.
*
* For an X11 framed window, the client window's server rectangle is
* inset from this rectangle by the frame's visible borders, and the
* frame window's server rectangle is outset by the invisible borders.
*
* For an X11 unframed window, the rectangle here directly matches
* the server's rectangle, since the visible and invisible borders
* are both 0.
*
* For an X11 CSD window, the client window's server rectangle is
* outset from this rectagle by the client-specified frame extents.
*
* For a Wayland window, this rectangle can simply be sent directly
* to the client.
*/
gboolean did_placement;
guint old_output_id;
MetaRectangle unconstrained_rect;
MetaRectangle constrained_rect;
MetaMoveResizeResultFlags result = 0;
@@ -3674,18 +3696,15 @@ meta_window_move_resize_internal (MetaWindow *window,
* resizing the old rectangle with the given gravity. */
if ((flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) == META_IS_RESIZE_ACTION)
{
MetaRectangle old_rect;
meta_window_get_client_root_coords (window, &old_rect);
meta_rectangle_resize_with_gravity (&old_rect,
meta_rectangle_resize_with_gravity (&window->rect,
&unconstrained_rect,
gravity,
client_rect.width,
client_rect.height);
frame_rect.width,
frame_rect.height);
}
else
{
unconstrained_rect = client_rect;
unconstrained_rect = frame_rect;
}
/* If this is only a move, then ignore the passed in size and
@@ -3706,15 +3725,21 @@ meta_window_move_resize_internal (MetaWindow *window,
MetaRectangle old_rect;
meta_window_get_frame_rect (window, &old_rect);
meta_window_client_rect_to_frame_rect (window, &constrained_rect, &constrained_rect);
meta_window_constrain (window,
flags,
gravity,
&old_rect,
&constrained_rect);
}
meta_window_frame_rect_to_client_rect (window, &constrained_rect, &constrained_rect);
/* If we did placement, then we need to save the position that the window
* was placed at to make sure that meta_window_move_resize_now places the
* window correctly.
*/
if (did_placement)
{
window->unconstrained_rect.x = constrained_rect.x;
window->unconstrained_rect.y = constrained_rect.y;
}
/* Do the protocol-specific move/resize logic */
@@ -3734,13 +3759,13 @@ meta_window_move_resize_internal (MetaWindow *window,
did_placement);
}
meta_window_update_monitor (window);
old_output_id = window->monitor->output_id;
/* Invariants leaving this function are:
* a) window->rect and frame->rect reflect the actual
* server-side size/pos of window->xwindow and frame->xwindow
* b) all constraints are obeyed by window->rect and frame->rect
*/
meta_window_update_monitor (window, flags & META_IS_USER_ACTION);
if (old_output_id != window->monitor->output_id &&
flags & META_IS_MOVE_ACTION && flags & META_IS_USER_ACTION)
window->preferred_output_id = window->monitor->output_id;
if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds)
{
@@ -3754,33 +3779,6 @@ meta_window_move_resize_internal (MetaWindow *window,
window->screen->active_workspace);
}
/**
* meta_window_move:
* @window: a #MetaWindow
* @user_op: bool to indicate whether or not this is a user operation
* @root_x_nw: desired x pos
* @root_y_nw: desired y pos
*
* Moves the window to the desired location on window's assigned workspace.
* NOTE: does NOT place according to the origin of the enclosing
* frame/window-decoration, but according to the origin of the window,
* itself.
*/
void
meta_window_move (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw)
{
MetaMoveResizeFlags flags;
MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
/**
* meta_window_move_frame:
* @window: a #MetaWindow
@@ -3799,10 +3797,13 @@ meta_window_move_frame (MetaWindow *window,
int root_x_nw,
int root_y_nw)
{
MetaMoveResizeFlags flags;
MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_window_move (window, user_op, rect.x, rect.y);
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
static void
@@ -3846,10 +3847,14 @@ meta_window_move_resize_frame (MetaWindow *window,
int w,
int h)
{
MetaMoveResizeFlags flags;
MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height);
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
/**
@@ -3880,41 +3885,18 @@ meta_window_move_to_monitor (MetaWindow *window,
window->tile_monitor_number = monitor;
meta_window_move_between_rects (window, &old_area, &new_area);
window->preferred_output_id = window->monitor->output_id;
if (window->fullscreen || window->override_redirect)
meta_screen_queue_check_fullscreen (window->screen);
}
void
meta_window_move_resize (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw,
int w,
int h)
{
MetaMoveResizeFlags flags;
MetaRectangle rect;
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) |
META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
rect.x = root_x_nw;
rect.y = root_y_nw;
rect.width = w;
rect.height = h;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
void
meta_window_resize_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity)
meta_window_resize_frame_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity)
{
MetaMoveResizeFlags flags;
MetaRectangle rect;
@@ -3929,11 +3911,11 @@ meta_window_resize_with_gravity (MetaWindow *window,
static void
meta_window_move_resize_now (MetaWindow *window)
{
meta_window_move_resize (window, FALSE,
window->unconstrained_rect.x,
window->unconstrained_rect.y,
window->unconstrained_rect.width,
window->unconstrained_rect.height);
meta_window_move_resize_frame (window, FALSE,
window->unconstrained_rect.x,
window->unconstrained_rect.y,
window->unconstrained_rect.width,
window->unconstrained_rect.height);
}
static gboolean
@@ -3976,36 +3958,6 @@ idle_move_resize (gpointer data)
return FALSE;
}
void
meta_window_get_position (MetaWindow *window,
int *x,
int *y)
{
if (window->frame)
{
if (x)
*x = window->frame->rect.x + window->frame->child_x;
if (y)
*y = window->frame->rect.y + window->frame->child_y;
}
else
{
if (x)
*x = window->rect.x;
if (y)
*y = window->rect.y;
}
}
void
meta_window_get_client_root_coords (MetaWindow *window,
MetaRectangle *rect)
{
meta_window_get_position (window, &rect->x, &rect->y);
rect->width = window->rect.width;
rect->height = window->rect.height;
}
void
meta_window_get_gravity_position (MetaWindow *window,
int gravity,
@@ -4108,23 +4060,23 @@ meta_window_get_session_geometry (MetaWindow *window,
}
/**
* meta_window_get_input_rect:
* meta_window_get_buffer_rect:
* @window: a #MetaWindow
* @rect: (out): pointer to an allocated #MetaRectangle
*
* Gets the rectangle that bounds @window that is responsive to mouse events.
* This includes decorations - the visible portion of its border - and (if
* present) any invisible area that we make make responsive to mouse clicks in
* order to allow convenient border dragging.
* Gets the rectangle that the pixmap or buffer of @window occupies.
*
* For X11 windows, this is the server-side geometry of the toplevel
* window.
*
* For Wayland windows, this is the bounding rectangle of the attached
* buffer.
*/
void
meta_window_get_input_rect (const MetaWindow *window,
MetaRectangle *rect)
meta_window_get_buffer_rect (const MetaWindow *window,
MetaRectangle *rect)
{
if (window->frame)
*rect = window->frame->rect;
else
*rect = window->rect;
*rect = window->buffer_rect;
}
/**
@@ -4234,30 +4186,7 @@ void
meta_window_get_frame_rect (const MetaWindow *window,
MetaRectangle *rect)
{
if (window->frame)
{
MetaFrameBorders borders;
*rect = window->frame->rect;
meta_frame_calc_borders (window->frame, &borders);
rect->x += borders.invisible.left;
rect->y += borders.invisible.top;
rect->width -= borders.invisible.left + borders.invisible.right;
rect->height -= borders.invisible.top + borders.invisible.bottom;
}
else
{
*rect = window->rect;
if (window->has_custom_frame_extents)
{
const GtkBorder *extents = &window->custom_frame_extents;
rect->x += extents->left;
rect->y += extents->top;
rect->width -= extents->left + extents->right;
rect->height -= extents->top + extents->bottom;
}
}
*rect = window->rect;
}
/**
@@ -4292,22 +4221,18 @@ void
meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect)
{
if (window->frame)
{
rect->x = window->frame->child_x;
rect->y = window->frame->child_y;
}
else
{
rect->x = 0;
rect->y = 0;
}
MetaFrameBorders borders;
rect->width = window->rect.width;
meta_frame_calc_borders (window->frame, &borders);
rect->x = borders.total.left;
rect->y = borders.total.top;
rect->width = window->rect.width - borders.visible.left - borders.visible.right;
if (window->shaded)
rect->height = 0;
else
rect->height = window->rect.height;
rect->height = window->rect.height - borders.visible.top - borders.visible.bottom;
}
void
@@ -4895,7 +4820,7 @@ meta_window_get_icon_geometry (MetaWindow *window,
/**
* meta_window_set_icon_geometry:
* @window: a #MetaWindow
* @rect: (allow-none): rectangle with the desired geometry or %NULL.
* @rect: (nullable): rectangle with the desired geometry or %NULL.
*
* Sets or unsets the location of the icon corresponding to the window. If
* set, the location should correspond to a dock, task bar or other user
@@ -5347,6 +5272,15 @@ meta_window_show_menu (MetaWindow *window,
meta_compositor_show_window_menu (window->display->compositor, window, menu, x, y);
}
void
meta_window_show_menu_for_rect (MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect)
{
g_return_if_fail (!window->override_redirect);
meta_compositor_show_window_menu_for_rect (window->display->compositor, window, menu, rect);
}
void
meta_window_shove_titlebar_onscreen (MetaWindow *window)
{
@@ -5694,7 +5628,7 @@ update_move (MetaWindow *window,
meta_screen_update_tile_preview (window->screen,
window->tile_mode != META_TILE_NONE);
meta_window_get_client_root_coords (window, &old);
meta_window_get_frame_rect (window, &old);
/* Don't allow movement in the maximized directions or while tiled */
if (window->maximized_horizontally || META_WINDOW_TILED_SIDE_BY_SIDE (window))
@@ -5704,15 +5638,13 @@ update_move (MetaWindow *window,
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_move (window,
old.x,
old.y,
&new_x,
&new_y,
update_move_timeout,
snap,
FALSE);
meta_window_move (window, TRUE, new_x, new_y);
meta_window_move_frame (window, TRUE, new_x, new_y);
}
/* When resizing a maximized window by using alt-middle-drag (resizing
@@ -5998,7 +5930,7 @@ update_resize (MetaWindow *window,
window->display->grab_resize_timeout_id = 0;
}
old = window->rect; /* Don't actually care about x,y */
meta_window_get_frame_rect (window, &old);
/* One sided resizing ought to actually be one-sided, despite the fact that
* aspect ratio windows don't interact nicely with the above stuff. So,
@@ -6026,8 +5958,6 @@ update_resize (MetaWindow *window,
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_resize (window,
old.width,
old.height,
&new_w,
&new_h,
gravity,
@@ -6037,13 +5967,7 @@ update_resize (MetaWindow *window,
if (new_unmaximize == window->display->grab_resize_unmaximize)
{
/* We don't need to update unless the specified width and height
* are actually different from what we had before.
*/
if (old.width != new_w || old.height != new_h)
{
meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
}
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
}
else
{
@@ -6582,8 +6506,8 @@ warp_grab_pointer (MetaWindow *window,
display->grab_anchor_root_y = *y;
display->grab_latest_motion_x = *x;
display->grab_latest_motion_y = *y;
meta_window_get_client_root_coords (window,
&display->grab_anchor_window_pos);
meta_window_get_frame_rect (window,
&display->grab_anchor_window_pos);
{
MetaBackend *backend = meta_get_backend ();
@@ -7396,7 +7320,7 @@ meta_window_get_frame_type (MetaWindow *window)
*
* Gets a region representing the outer bounds of the window's frame.
*
* Return value: (transfer none) (allow-none): a #cairo_region_t
* Return value: (transfer none) (nullable): a #cairo_region_t
* holding the outer bounds of the window, or %NULL if the window
* doesn't have a frame.
*/
@@ -7441,7 +7365,7 @@ meta_window_is_attached_dialog (MetaWindow *window)
* - there is no 3rd window stacked between both tiled windows that's
* partially visible in the common edge.
*
* Return value: (transfer none) (allow-none): the matching tiled window or
* Return value: (transfer none) (nullable): the matching tiled window or
* %NULL if it doesn't exist.
*/
MetaWindow *
@@ -7760,8 +7684,8 @@ window_has_pointer_x11 (MetaWindow *window)
return meta_display_lookup_x_window (display, child) == window;
}
static gboolean
window_has_pointer (MetaWindow *window)
gboolean
meta_window_has_pointer (MetaWindow *window)
{
if (meta_is_wayland_compositor ())
return window_has_pointer_wayland (window);
@@ -7790,10 +7714,10 @@ window_focus_on_pointer_rest_callback (gpointer data)
{
focus_data->pointer_x = root_x;
focus_data->pointer_y = root_y;
return TRUE;
return G_SOURCE_CONTINUE;
}
if (!window_has_pointer (window))
if (!meta_window_has_pointer (window))
goto out;
timestamp = meta_display_get_current_time_roundtrip (display);
@@ -7801,7 +7725,7 @@ window_focus_on_pointer_rest_callback (gpointer data)
out:
display->focus_timeout_id = 0;
return FALSE;
return G_SOURCE_REMOVE;
}
/* The interval, in milliseconds, we use in focus-follows-mouse
@@ -7890,6 +7814,15 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
if (display->grab_op != META_GRAB_OP_NONE)
return FALSE;
/* Some windows might not ask for input, in which case we might be here
* because we selected for ButtonPress on the root window. In that case,
* we have to take special care not to act for an override-redirect window.
*
* Consume the event in this case, though, since we don't want it passed
* to the compositor or UI. */
if (window->override_redirect)
return TRUE;
/* We have three passive button grabs:
* - on any button, without modifiers => focuses and maybe raises the window
* - on resize button, with modifiers => start an interactive resizing
@@ -8038,12 +7971,6 @@ meta_window_set_surface_mapped (MetaWindow *window,
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
}
Window
meta_window_get_toplevel_xwindow (MetaWindow *window)
{
return window->frame ? window->frame->xwindow : window->xwindow;
}
void
meta_window_set_custom_frame_extents (MetaWindow *window,
GtkBorder *extents)

View File

@@ -1040,6 +1040,45 @@ void
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
GSList *struts)
{
MetaScreen *screen = workspace->screen;
GSList *l;
for (l = struts; l; l = l->next)
{
MetaStrut *strut = l->data;
int idx = meta_screen_get_monitor_index_for_rect (screen, &strut->rect);
switch (strut->side)
{
case META_SIDE_TOP:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_UP))
continue;
strut->rect.height += strut->rect.y;
strut->rect.y = 0;
break;
case META_SIDE_BOTTOM:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_DOWN))
continue;
strut->rect.height = screen->rect.height - strut->rect.y;
break;
case META_SIDE_LEFT:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_LEFT))
continue;
strut->rect.width += strut->rect.x;
strut->rect.x = 0;
break;
case META_SIDE_RIGHT:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_RIGHT))
continue;
strut->rect.width = screen->rect.width - strut->rect.x;
break;
}
}
/* Reordering doesn't actually matter, so we don't catch all
* no-impact changes, but this is just a (possibly unnecessary
* anyways) optimization */

View File

@@ -5,14 +5,9 @@ includedir=@includedir@
girdir=@libdir@/mutter
typelibdir=@libdir@/mutter
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter
Description: Mutter window manager library
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
Version: @VERSION@
Libs: -L${libdir} -lmutter
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}
Cflags: -I${includedir}/mutter

View File

@@ -43,8 +43,6 @@
#define META_VIRTUAL_CORE_POINTER_ID 2
#define META_VIRTUAL_CORE_KEYBOARD_ID 3
typedef struct _MetaResizePopup MetaResizePopup;
/**
* MetaFrameFlags:
* @META_FRAME_ALLOWS_DELETE: frame allows delete

View File

@@ -101,9 +101,8 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
gboolean did_placement);
void meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen);
void meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
MetaWindow *window,
gboolean no_delay_frame);
@@ -127,5 +126,9 @@ void meta_compositor_show_window_menu (MetaCompositor *compositor,
MetaWindowMenuType menu,
int x,
int y);
void meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
#endif /* META_COMPOSITOR_H */

View File

@@ -94,7 +94,6 @@ guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display);
GList* meta_display_get_tab_list (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace);
MetaWindow* meta_display_get_tab_next (MetaDisplay *display,

View File

@@ -25,6 +25,7 @@
#include <meta/types.h>
#include <meta/compositor.h>
#include <meta/compositor-mutter.h>
#include <meta/meta-version.h>
#include <clutter/clutter.h>
#include <X11/extensions/Xfixes.h>
@@ -170,6 +171,11 @@ struct _MetaPluginClass
int x,
int y);
void (*show_window_menu_for_rect) (MetaPlugin *plugin,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
/**
* MetaPluginClass::kill_window_effects:
* @actor: a #MetaWindowActor
@@ -294,10 +300,10 @@ struct _MetaPluginVersion
#define META_PLUGIN_DECLARE(ObjectName, object_name) \
G_MODULE_EXPORT MetaPluginVersion meta_plugin_version = \
{ \
MUTTER_MAJOR_VERSION, \
MUTTER_MINOR_VERSION, \
MUTTER_MICRO_VERSION, \
MUTTER_PLUGIN_API_VERSION \
META_MAJOR_VERSION, \
META_MINOR_VERSION, \
META_MICRO_VERSION, \
META_PLUGIN_API_VERSION \
}; \
\
static GType g_define_type_id = 0; \

View File

@@ -0,0 +1,28 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Rico Tzschichholz
*
* 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_VERSION_H
#define META_VERSION_H
#define META_MAJOR_VERSION @MUTTER_MAJOR_VERSION@
#define META_MINOR_VERSION @MUTTER_MINOR_VERSION@
#define META_MICRO_VERSION @MUTTER_MICRO_VERSION@
#define META_PLUGIN_API_VERSION @MUTTER_PLUGIN_API_VERSION@
#endif

View File

@@ -108,7 +108,7 @@ gboolean meta_window_appears_focused (MetaWindow *window);
gboolean meta_window_is_shaded (MetaWindow *window);
gboolean meta_window_is_override_redirect (MetaWindow *window);
gboolean meta_window_is_skip_taskbar (MetaWindow *window);
void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_buffer_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_frame_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect) G_GNUC_DEPRECATED;
@@ -147,7 +147,6 @@ const char * meta_window_get_gtk_window_object_path (MetaWindow *window);
const char * meta_window_get_gtk_app_menu_object_path (MetaWindow *window);
const char * meta_window_get_gtk_menubar_object_path (MetaWindow *window);
void meta_window_move(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw);
void meta_window_move_frame(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw);
void meta_window_move_resize_frame (MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw, int w, int h);
void meta_window_move_to_monitor (MetaWindow *window, int monitor);

View File

@@ -224,8 +224,6 @@ meta_frames_init (MetaFrames *frames)
update_style_contexts (frames);
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
meta_prefs_add_listener (prefs_changed_callback, frames);
}
@@ -1138,6 +1136,64 @@ meta_frame_right_click_event(MetaUIFrame *frame,
return meta_frame_titlebar_event (frame, event, action);
}
static gboolean
meta_frames_try_grab_op (MetaFrames *frames,
MetaUIFrame *frame,
MetaGrabOp op,
gdouble grab_x,
gdouble grab_y,
guint32 time)
{
Display *display;
gboolean ret;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
ret = meta_core_begin_grab_op (display,
frame->xwindow,
op,
FALSE,
TRUE,
frame->grab_button,
0,
time,
grab_x, grab_y);
if (!ret)
{
frames->current_grab_op = op;
frames->grab_frame = frame;
frames->grab_x = grab_x;
frames->grab_y = grab_y;
}
return ret;
}
static gboolean
meta_frames_retry_grab_op (MetaFrames *frames,
guint time)
{
Display *display;
MetaGrabOp op;
if (frames->current_grab_op == META_GRAB_OP_NONE)
return TRUE;
op = frames->current_grab_op;
frames->current_grab_op = META_GRAB_OP_NONE;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
return meta_core_begin_grab_op (display,
frames->grab_frame->xwindow,
op,
FALSE,
TRUE,
frames->grab_frame->grab_button,
0,
time,
frames->grab_x,
frames->grab_y);
}
static gboolean
meta_frames_button_press_event (GtkWidget *widget,
GdkEventButton *event)
@@ -1192,6 +1248,8 @@ meta_frames_button_press_event (GtkWidget *widget,
if (meta_core_get_grab_op (display) != META_GRAB_OP_NONE)
return FALSE; /* already up to something */
frame->grab_button = event->button;
if (event->button == 1 &&
(control == META_FRAME_CONTROL_MAXIMIZE ||
control == META_FRAME_CONTROL_UNMAXIMIZE ||
@@ -1218,30 +1276,36 @@ meta_frames_button_press_event (GtkWidget *widget,
{
MetaFrameGeometry fgeom;
GdkRectangle *rect;
MetaRectangle root_rect;
MetaWindowMenuType menu;
int dx, dy;
int win_x, win_y;
meta_frames_calc_geometry (frames, frame, &fgeom);
rect = control_rect (control, &fgeom);
/* get delta to convert to root coords */
dx = event->x_root - event->x;
dy = event->y_root - event->y;
/* convert to root coords */
win_x = event->x_root - event->x;
win_y = event->y_root - event->y;
/* Align to the right end of the menu rectangle if RTL */
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
dx += rect->width;
root_rect.x = win_x + rect->x;
root_rect.y = win_y + rect->y;
root_rect.width = rect->width;
root_rect.height = rect->height;
menu = control == META_FRAME_CONTROL_MENU ? META_WINDOW_MENU_WM
: META_WINDOW_MENU_APP;
meta_core_show_window_menu (display,
frame->xwindow,
menu,
rect->x + dx,
rect->y + rect->height + dy,
event->time);
/* if the compositor takes a grab for showing the menu, we will
* get a LeaveNotify event we want to ignore, to keep the pressed
* button state while the menu is open
*/
frame->maybe_ignore_leave_notify = TRUE;
meta_core_show_window_menu_for_rect (display,
frame->xwindow,
menu,
&root_rect,
event->time);
}
}
else if (event->button == 1 &&
@@ -1289,16 +1353,9 @@ meta_frames_button_press_event (GtkWidget *widget,
break;
}
meta_core_begin_grab_op (display,
frame->xwindow,
op,
TRUE,
TRUE,
event->button,
0,
event->time,
event->x_root,
event->y_root);
meta_frames_try_grab_op (frames, frame, op,
event->x_root, event->y_root,
event->time);
}
else if (control == META_FRAME_CONTROL_TITLE &&
event->button == 1)
@@ -1311,16 +1368,10 @@ meta_frames_button_press_event (GtkWidget *widget,
if (flags & META_FRAME_ALLOWS_MOVE)
{
meta_core_begin_grab_op (display,
frame->xwindow,
meta_frames_try_grab_op (frames, frame,
META_GRAB_OP_MOVING,
TRUE,
TRUE,
event->button,
0,
event->time,
event->x_root,
event->y_root);
event->x_root, event->y_root,
event->time);
}
}
else if (event->button == 2)
@@ -1345,6 +1396,7 @@ meta_frames_button_release_event (GtkWidget *widget,
frames = META_FRAMES (widget);
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
frames->current_grab_op = META_GRAB_OP_NONE;
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
if (frame == NULL)
@@ -1506,7 +1558,8 @@ meta_frames_update_prelit_control (MetaFrames *frames,
break;
}
if (control == frame->prelit_control)
if (control == frame->prelit_control &&
frame->button_state == META_BUTTON_STATE_PRELIGHT)
return;
/* Save the old control so we can unprelight it */
@@ -1555,6 +1608,10 @@ meta_frames_motion_notify_event (GtkWidget *widget,
meta_frames_update_prelit_control (frames, frame, control);
}
if ((event->state & GDK_BUTTON1_MASK) &&
frames->current_grab_op != META_GRAB_OP_NONE)
meta_frames_retry_grab_op (frames, event->time);
return TRUE;
}
@@ -1575,47 +1632,23 @@ meta_frames_destroy_event (GtkWidget *widget,
}
static void
setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset)
{
GdkWindow *parent = gdk_window_get_parent (window);
cairo_pattern_t *bg_pattern;
bg_pattern = gdk_window_get_background_pattern (window);
if (bg_pattern == NULL && parent)
{
gint window_x, window_y;
gdk_window_get_position (window, &window_x, &window_y);
setup_bg_cr (cr, parent, x_offset + window_x, y_offset + window_y);
}
else if (bg_pattern)
{
cairo_translate (cr, - x_offset, - y_offset);
cairo_set_source (cr, bg_pattern);
cairo_translate (cr, x_offset, y_offset);
}
}
static void
clip_region_to_visible_frame_border (cairo_region_t *region,
MetaUIFrame *frame)
static cairo_region_t *
get_visible_frame_border_region (MetaUIFrame *frame)
{
MetaRectangle frame_rect;
cairo_rectangle_int_t area;
cairo_region_t *frame_border;
MetaFrameFlags flags;
MetaFrameType type;
MetaFrameBorders borders;
Display *display;
int frame_width, frame_height;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
meta_core_get (display, frame->xwindow,
META_CORE_GET_FRAME_FLAGS, &flags,
META_CORE_GET_FRAME_TYPE, &type,
META_CORE_GET_FRAME_WIDTH, &frame_width,
META_CORE_GET_FRAME_HEIGHT, &frame_height,
META_CORE_GET_FRAME_RECT, &frame_rect,
META_CORE_GET_END);
meta_theme_get_frame_borders (meta_theme_get_current (),
@@ -1625,8 +1658,8 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
/* Visible frame rect */
area.x = borders.invisible.left;
area.y = borders.invisible.top;
area.width = frame_width - borders.invisible.left - borders.invisible.right;
area.height = frame_height - borders.invisible.top - borders.invisible.bottom;
area.width = frame_rect.width;
area.height = frame_rect.height;
frame_border = cairo_region_create_rectangle (&area);
@@ -1638,9 +1671,7 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
/* Visible frame border */
cairo_region_subtract_rectangle (frame_border, &area);
cairo_region_intersect (region, frame_border);
cairo_region_destroy (frame_border);
return frame_border;
}
#define TAU (2*M_PI)
@@ -1739,42 +1770,42 @@ meta_frames_get_mask (MetaFrames *frames,
cairo_restore (cr);
}
/* XXX -- this is disgusting. Find a better approach here.
* Use multiple widgets? */
static MetaUIFrame *
find_frame_to_draw (MetaFrames *frames,
cairo_t *cr)
{
GHashTableIter iter;
MetaUIFrame *frame;
g_hash_table_iter_init (&iter, frames->frames);
while (g_hash_table_iter_next (&iter, (gpointer *) &frame, NULL))
if (gtk_cairo_should_draw_window (cr, frame->window))
return frame;
return NULL;
}
static gboolean
meta_frames_draw (GtkWidget *widget,
cairo_t *cr)
{
MetaUIFrame *frame;
MetaFrames *frames;
cairo_rectangle_int_t clip;
cairo_region_t *region;
cairo_surface_t *target;
frames = META_FRAMES (widget);
target = cairo_get_target (cr);
gdk_cairo_get_clip_rectangle (cr, &clip);
g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
frame = find_frame_to_draw (frames, cr);
if (frame == NULL)
return FALSE;
region = cairo_region_create_rectangle (&clip);
clip_region_to_visible_frame_border (region, frame);
if (cairo_region_is_empty (region))
goto out;
region = get_visible_frame_border_region (frame);
gdk_cairo_region (cr, region);
cairo_clip (cr);
cairo_save (cr);
setup_bg_cr (cr, frame->window, 0, 0);
cairo_paint (cr);
cairo_restore (cr);
meta_frames_paint (frames, frame, cr);
out:
cairo_region_destroy (region);
return TRUE;
@@ -1933,6 +1964,8 @@ meta_frames_enter_notify_event (GtkWidget *widget,
if (frame == NULL)
return FALSE;
frame->maybe_ignore_leave_notify = FALSE;
control = get_control (frames, frame, event->x, event->y);
meta_frames_update_prelit_control (frames, frame, control);
@@ -1945,6 +1978,8 @@ meta_frames_leave_notify_event (GtkWidget *widget,
{
MetaUIFrame *frame;
MetaFrames *frames;
Display *display;
MetaGrabOp grab_op;
frames = META_FRAMES (widget);
@@ -1952,6 +1987,18 @@ meta_frames_leave_notify_event (GtkWidget *widget,
if (frame == NULL)
return FALSE;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
grab_op = meta_core_get_grab_op (display);
/* ignore the first LeaveNotify event after opening a window menu
* if it is the result of a compositor grab
*/
frame->maybe_ignore_leave_notify = frame->maybe_ignore_leave_notify &&
grab_op == META_GRAB_OP_COMPOSITOR;
if (frame->maybe_ignore_leave_notify)
return FALSE;
meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
return TRUE;

View File

@@ -80,6 +80,7 @@ struct _MetaUIFrame
int text_height;
char *title; /* NULL once we have a layout */
guint shape_applied : 1;
guint maybe_ignore_leave_notify : 1;
/* FIXME get rid of this, it can just be in the MetaFrames struct */
MetaFrameControl prelit_control;
@@ -99,6 +100,12 @@ struct _MetaFrames
GtkStyleContext *normal_style;
GHashTable *style_variants;
MetaGrabOp current_grab_op;
MetaUIFrame *grab_frame;
guint grab_button;
gdouble grab_x;
gdouble grab_y;
Window grab_xwindow;
};

View File

@@ -29,6 +29,8 @@
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef struct _MetaResizePopup MetaResizePopup;
MetaResizePopup* meta_ui_resize_popup_new (Display *display,
int screen_number);
void meta_ui_resize_popup_free (MetaResizePopup *popup);

View File

@@ -56,8 +56,6 @@
((int)((color).green * 255) << 8) | \
((int)((color).blue * 255))))
#define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255))
#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s)))
#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255)))
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
@@ -94,8 +92,8 @@ colorize_pixbuf (GdkPixbuf *orig,
guchar *dest_pixels;
pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig),
gdk_pixbuf_get_bits_per_sample (orig),
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
gdk_pixbuf_get_bits_per_sample (orig),
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
if (pixbuf == NULL)
return NULL;
@@ -795,19 +793,19 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
&n_right, &fgeom->above_rect))
continue;
else if (strip_button (left_func_rects, left_bg_rects,
&n_left, &fgeom->stick_rect))
&n_left, &fgeom->stick_rect))
continue;
else if (strip_button (right_func_rects, right_bg_rects,
&n_right, &fgeom->stick_rect))
continue;
else if (strip_button (left_func_rects, left_bg_rects,
&n_left, &fgeom->shade_rect))
&n_left, &fgeom->shade_rect))
continue;
else if (strip_button (right_func_rects, right_bg_rects,
&n_right, &fgeom->shade_rect))
continue;
else if (strip_button (left_func_rects, left_bg_rects,
&n_left, &fgeom->min_rect))
&n_left, &fgeom->min_rect))
continue;
else if (strip_button (right_func_rects, right_bg_rects,
&n_right, &fgeom->min_rect))
@@ -926,12 +924,11 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
rect->clickable.width = button_width;
}
rect->clickable.y = 0;
rect->clickable.height = button_height + button_y;
}
else
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
rect->clickable.y = 0;
rect->clickable.height = button_height + button_y;
}
else
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
x = rect->visible.x + rect->visible.width + layout->button_border.right;
if (left_buttons_has_spacer[i])
@@ -1192,10 +1189,8 @@ meta_color_spec_new_from_string (const char *str,
MetaColorSpec *spec;
spec = NULL;
if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':' &&
str[4] == 'c' && str[5] == 'u' && str[6] == 's' && str[7] == 't' &&
str[8] == 'o' && str[9] == 'm')
if (strncmp (str, "gtk:custom", 10) == 0)
{
const char *color_name_start, *fallback_str_start, *end;
char *color_name;
@@ -1270,7 +1265,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.gtkcustom.color_name = color_name;
spec->data.gtkcustom.fallback = fallback;
}
else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':')
else if (strncmp (str, "gtk:", 4) == 0)
{
/* GTK color */
const char *bracket;
@@ -1337,8 +1332,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.gtk.component = component;
g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
}
else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' &&
str[4] == 'd' && str[5] == '/')
else if (strncmp (str, "blend/", 6) == 0)
{
/* blend */
char **split;
@@ -1406,8 +1400,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.blend.background = bg;
spec->data.blend.foreground = fg;
}
else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' &&
str[4] == 'e' && str[5] == '/')
else if (strncmp (str, "shade/", 6) == 0)
{
/* shade */
char **split;
@@ -1704,20 +1697,12 @@ op_from_string (const char *p,
return POS_OP_MOD;
case '`':
if (p[0] == '`' &&
p[1] == 'm' &&
p[2] == 'a' &&
p[3] == 'x' &&
p[4] == '`')
if (strncmp (p, "`max`", 5) == 0)
{
*len = 5;
return POS_OP_MAX;
}
else if (p[0] == '`' &&
p[1] == 'm' &&
p[2] == 'i' &&
p[3] == 'n' &&
p[4] == '`')
else if (strncmp (p, "`min`", 5) == 0)
{
*len = 5;
return POS_OP_MIN;
@@ -3067,7 +3052,7 @@ meta_draw_op_free (MetaDrawOp *op)
g_object_unref (G_OBJECT (op->data.image.pixbuf));
if (op->data.image.colorize_spec)
meta_color_spec_free (op->data.image.colorize_spec);
meta_color_spec_free (op->data.image.colorize_spec);
if (op->data.image.colorize_cache_pixbuf)
g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
@@ -3418,32 +3403,6 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
switch (op->type)
{
case META_DRAW_LINE:
break;
case META_DRAW_RECTANGLE:
if (op->data.rectangle.filled)
{
GdkRGBA color;
meta_color_spec_render (op->data.rectangle.color_spec,
context,
&color);
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
FALSE,
8, width, height);
gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color));
}
break;
case META_DRAW_ARC:
break;
case META_DRAW_CLIP:
break;
case META_DRAW_TINT:
{
GdkRGBA color;
@@ -3502,12 +3461,11 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
}
break;
case META_DRAW_IMAGE:
{
if (op->data.image.colorize_spec)
{
GdkRGBA color;
if (op->data.image.colorize_spec)
{
GdkRGBA color;
meta_color_spec_render (op->data.image.colorize_spec,
context, &color);
@@ -3535,24 +3493,18 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
}
}
else
{
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
}
else
{
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
op->data.image.alpha_spec,
op->data.image.fill_type,
width, height,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
}
}
break;
}
case META_DRAW_GTK_ARROW:
case META_DRAW_GTK_BOX:
case META_DRAW_GTK_VLINE:
break;
case META_DRAW_ICON:
if (info->mini_icon &&
width <= gdk_pixbuf_get_width (info->mini_icon) &&
@@ -3570,12 +3522,15 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
FALSE, FALSE);
break;
case META_DRAW_LINE:
case META_DRAW_RECTANGLE:
case META_DRAW_ARC:
case META_DRAW_CLIP:
case META_DRAW_GTK_ARROW:
case META_DRAW_GTK_BOX:
case META_DRAW_GTK_VLINE:
case META_DRAW_TITLE:
break;
case META_DRAW_OP_LIST:
break;
case META_DRAW_TILE:
break;
}
@@ -4046,8 +4001,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
d_rect.height = parse_size_unchecked (op->data.op_list.height, env);
meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
style_gtk, cr, info,
d_rect);
style_gtk, cr, info, d_rect);
}
break;
@@ -4084,8 +4038,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
while (tile.y < (ry + rheight))
{
meta_draw_op_list_draw_with_style (op->data.tile.op_list,
style_gtk, cr, info,
tile);
style_gtk, cr, info, tile);
tile.y += tile.height;
}
@@ -6569,216 +6522,6 @@ hls_to_rgb (gdouble *h,
}
}
#if 0
/* These are some functions I'm saving to use in optimizing
* MetaDrawOpList, namely to pre-composite pixbufs on client side
* prior to rendering to the server
*/
static void
draw_bg_solid_composite (const MetaTextureSpec *bg,
const MetaTextureSpec *fg,
double alpha,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
MetaTextureDrawMode mode,
double xalign,
double yalign,
int x,
int y,
int width,
int height)
{
GdkRGBA bg_color;
g_assert (bg->type == META_TEXTURE_SOLID);
g_assert (fg->type != META_TEXTURE_COMPOSITE);
g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
meta_color_spec_render (bg->data.solid.color_spec,
widget,
&bg_color);
switch (fg->type)
{
case META_TEXTURE_SOLID:
{
GdkRGBA fg_color;
meta_color_spec_render (fg->data.solid.color_spec,
widget,
&fg_color);
color_composite (&bg_color, &fg_color,
alpha, &fg_color);
draw_color_rectangle (widget, drawable, &fg_color, clip,
x, y, width, height);
}
break;
case META_TEXTURE_GRADIENT:
/* FIXME I think we could just composite all the colors in
* the gradient prior to generating the gradient?
*/
/* FALL THRU */
case META_TEXTURE_IMAGE:
{
GdkPixbuf *pixbuf;
GdkPixbuf *composited;
pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
width, height);
if (pixbuf == NULL)
return;
composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
gdk_pixbuf_get_has_alpha (pixbuf), 8,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
if (composited == NULL)
{
g_object_unref (G_OBJECT (pixbuf));
return;
}
gdk_pixbuf_composite_color (pixbuf,
composited,
0, 0,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
0.0, 0.0, /* offsets */
1.0, 1.0, /* scale */
GDK_INTERP_BILINEAR,
255 * alpha,
0, 0, /* check offsets */
0, /* check size */
GDK_COLOR_RGB (bg_color),
GDK_COLOR_RGB (bg_color));
/* Need to draw background since pixbuf is not
* necessarily covering the whole thing
*/
draw_color_rectangle (widget, drawable, &bg_color, clip,
x, y, width, height);
render_pixbuf_aligned (drawable, clip, composited,
xalign, yalign,
x, y, width, height);
g_object_unref (G_OBJECT (pixbuf));
g_object_unref (G_OBJECT (composited));
}
break;
case META_TEXTURE_BLANK:
case META_TEXTURE_COMPOSITE:
case META_TEXTURE_SHAPE_LIST:
g_assert_not_reached ();
break;
}
}
static void
draw_bg_gradient_composite (const MetaTextureSpec *bg,
const MetaTextureSpec *fg,
double alpha,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
MetaTextureDrawMode mode,
double xalign,
double yalign,
int x,
int y,
int width,
int height)
{
g_assert (bg->type == META_TEXTURE_GRADIENT);
g_assert (fg->type != META_TEXTURE_COMPOSITE);
g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
switch (fg->type)
{
case META_TEXTURE_SOLID:
case META_TEXTURE_GRADIENT:
case META_TEXTURE_IMAGE:
{
GdkPixbuf *bg_pixbuf;
GdkPixbuf *fg_pixbuf;
GdkPixbuf *composited;
int fg_width, fg_height;
bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255,
width, height);
if (bg_pixbuf == NULL)
return;
fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
width, height);
if (fg_pixbuf == NULL)
{
g_object_unref (G_OBJECT (bg_pixbuf));
return;
}
/* gradients always fill the entire target area */
g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width);
g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height);
composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
gdk_pixbuf_get_has_alpha (bg_pixbuf), 8,
gdk_pixbuf_get_width (bg_pixbuf),
gdk_pixbuf_get_height (bg_pixbuf));
if (composited == NULL)
{
g_object_unref (G_OBJECT (bg_pixbuf));
g_object_unref (G_OBJECT (fg_pixbuf));
return;
}
fg_width = gdk_pixbuf_get_width (fg_pixbuf);
fg_height = gdk_pixbuf_get_height (fg_pixbuf);
/* If we wanted to be all cool we could deal with the
* offsets and try to composite only in the clip rectangle,
* but I just don't care enough to figure it out.
*/
gdk_pixbuf_composite (fg_pixbuf,
composited,
x + (width - fg_width) * xalign,
y + (height - fg_height) * yalign,
gdk_pixbuf_get_width (fg_pixbuf),
gdk_pixbuf_get_height (fg_pixbuf),
0.0, 0.0, /* offsets */
1.0, 1.0, /* scale */
GDK_INTERP_BILINEAR,
255 * alpha);
gdk_cairo_set_source_pixbuf (cr, composited, x, y);
cairo_paint (cr);
g_object_unref (G_OBJECT (bg_pixbuf));
g_object_unref (G_OBJECT (fg_pixbuf));
g_object_unref (G_OBJECT (composited));
}
break;
case META_TEXTURE_BLANK:
case META_TEXTURE_SHAPE_LIST:
case META_TEXTURE_COMPOSITE:
g_assert_not_reached ();
break;
}
}
#endif
/**
* meta_theme_earliest_version_with_button:
* @type: the button type

View File

@@ -26,6 +26,7 @@
#include <meta/util.h>
#include "core.h"
#include "theme-private.h"
#include "x11/events.h"
#include <string.h>
#include <stdlib.h>
@@ -119,7 +120,6 @@ maybe_redirect_mouse_event (XEvent *xevent)
switch (xev->evtype)
{
case XI_TouchBegin:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_Motion:
@@ -147,19 +147,11 @@ maybe_redirect_mouse_event (XEvent *xevent)
gmanager = gdk_display_get_device_manager (gdisplay);
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
/* If GDK already thinks it has a grab, we better let it see events; this
* is the menu-navigation case and events need to get sent to the appropriate
* (client-side) subwindow for individual menu items.
*/
if (gdk_display_device_is_grabbed (gdisplay, gdevice))
return FALSE;
switch (xev->evtype)
{
case XI_TouchBegin:
case XI_ButtonPress:
case XI_ButtonRelease:
if (xev_d->evtype == XI_ButtonPress || xev_d->evtype == XI_TouchBegin)
if (xev_d->evtype == XI_ButtonPress)
{
GtkSettings *settings = gtk_settings_get_default ();
int double_click_time;
@@ -171,10 +163,7 @@ maybe_redirect_mouse_event (XEvent *xevent)
"gtk-double-click-distance", &double_click_distance,
NULL);
if (xev->evtype == XI_TouchBegin)
button = 1;
else
button = xev_d->detail;
button = xev_d->detail;
if (button == ui->button_click_number &&
xev_d->event == ui->button_click_window &&
@@ -216,6 +205,12 @@ maybe_redirect_mouse_event (XEvent *xevent)
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
gevent->motion.type = GDK_MOTION_NOTIFY;
gevent->motion.window = g_object_ref (gdk_window);
gevent->motion.time = xev_d->time;
gevent->motion.x_root = xev_d->root_x;
gevent->motion.y_root = xev_d->root_y;
if (XIMaskIsSet (xev_d->buttons.mask, 1))
gevent->motion.state |= GDK_BUTTON1_MASK;
break;
case XI_Enter:
case XI_Leave:
@@ -237,15 +232,11 @@ maybe_redirect_mouse_event (XEvent *xevent)
return TRUE;
}
static GdkFilterReturn
ui_filter_func (GdkXEvent *xevent,
GdkEvent *event,
static void
ui_filter_func (gpointer xevent,
gpointer data)
{
if (maybe_redirect_mouse_event (xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
maybe_redirect_mouse_event (xevent);
}
MetaUI*
@@ -271,7 +262,7 @@ meta_ui_new (Display *xdisplay,
*/
gtk_widget_show (GTK_WIDGET (ui->frames));
gdk_window_add_filter (NULL, ui_filter_func, NULL);
meta_display_events_x11_add_func (ui_filter_func, NULL);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
@@ -288,7 +279,7 @@ meta_ui_free (MetaUI *ui)
gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL);
gdk_window_remove_filter (NULL, ui_filter_func, NULL);
meta_display_events_x11_add_func (ui_filter_func, NULL);
g_free (ui);
}

View File

@@ -200,8 +200,6 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
pointer->cursor_surface = NULL;
pointer->cursor_surface_destroy_listener.notify = pointer_handle_cursor_surface_destroy;
pointer->hotspot_x = 16;
pointer->hotspot_y = 16;
pointer->default_grab.interface = &default_pointer_grab_interface;
pointer->default_grab.pointer = pointer;
@@ -383,9 +381,13 @@ handle_scroll_event (MetaWaylandPointer *pointer,
case CLUTTER_SCROLL_SMOOTH:
{
double dx, dy;
/* Clutter smooth scroll events are in discrete steps (1 step = 1.0 long
* vector along one axis). To convert to smooth scroll events that are
* in pointer motion event space, multiply the vector with the 10. */
const double factor = 10.0;
clutter_event_get_scroll_delta (event, &dx, &dy);
x_value = wl_fixed_from_double (dx);
y_value = wl_fixed_from_double (dy);
x_value = wl_fixed_from_double (dx) * factor;
y_value = wl_fixed_from_double (dy) * factor;
}
break;

View File

@@ -59,7 +59,10 @@ seat_get_touch (struct wl_client *client,
struct wl_resource *resource,
uint32_t id)
{
/* Touch not supported */
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandTouch *touch = &seat->touch;
meta_wayland_touch_create_new_resource (touch, client, resource, id);
}
static const struct wl_seat_interface seat_interface = {
@@ -84,7 +87,8 @@ bind_seat (struct wl_client *client,
wl_seat_send_capabilities (resource,
WL_SEAT_CAPABILITY_POINTER |
WL_SEAT_CAPABILITY_KEYBOARD);
WL_SEAT_CAPABILITY_KEYBOARD |
WL_SEAT_CAPABILITY_TOUCH);
if (version >= WL_SEAT_NAME_SINCE_VERSION)
wl_seat_send_name (resource, "seat0");
@@ -101,6 +105,7 @@ meta_wayland_seat_new (struct wl_display *display)
meta_wayland_pointer_init (&seat->pointer, display);
meta_wayland_keyboard_init (&seat->keyboard, display);
meta_wayland_touch_init (&seat->touch, display);
seat->display = display;
@@ -120,6 +125,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
{
meta_wayland_pointer_release (&seat->pointer);
meta_wayland_keyboard_release (&seat->keyboard);
meta_wayland_touch_release (&seat->touch);
g_slice_free (MetaWaylandSeat, seat);
}
@@ -142,6 +148,12 @@ meta_wayland_seat_update (MetaWaylandSeat *seat,
meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
break;
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
meta_wayland_touch_update (&seat->touch, event);
break;
default:
break;
}
@@ -163,6 +175,10 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
case CLUTTER_KEY_RELEASE:
return meta_wayland_keyboard_handle_event (&seat->keyboard,
(const ClutterKeyEvent *) event);
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
return meta_wayland_touch_handle_event (&seat->touch, event);
default:
break;

View File

@@ -28,6 +28,7 @@
#include "meta-wayland-types.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-touch.h"
struct _MetaWaylandDataOffer
{
@@ -53,6 +54,7 @@ struct _MetaWaylandSeat
struct wl_list data_device_resource_list;
MetaWaylandPointer pointer;
MetaWaylandKeyboard keyboard;
MetaWaylandTouch touch;
struct wl_display *display;
};

View File

@@ -1018,9 +1018,9 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
}
window = meta_window_wayland_new (meta_get_display (), surface);
meta_window_move (window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
meta_window_move_frame (window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
window->showing_for_first_time = FALSE;
window->placed = TRUE;
meta_window_set_transient_for (window, parent_surf->window);
@@ -1212,9 +1212,9 @@ wl_shell_surface_set_transient (struct wl_client *client,
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);
meta_window_move_frame (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
}
@@ -1247,9 +1247,9 @@ wl_shell_surface_set_popup (struct wl_client *client,
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);
meta_window_move_frame (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);
@@ -1677,11 +1677,10 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
}
pending_state_init (&surface->sub.pending);
surface->sub.synchronous = TRUE;
surface->sub.parent = parent;
surface->sub.parent_destroy_listener.notify =
surface_handle_parent_surface_destroyed;
wl_resource_add_destroy_listener (parent->resource,
&surface->sub.parent_destroy_listener);
surface->sub.parent_destroy_listener.notify = surface_handle_parent_surface_destroyed;
wl_resource_add_destroy_listener (parent->resource, &surface->sub.parent_destroy_listener);
parent->subsurfaces = g_list_append (parent->subsurfaces, surface);
clutter_actor_add_child (CLUTTER_ACTOR (parent->surface_actor),

View File

@@ -0,0 +1,547 @@
/*
* Wayland Support
*
* 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#define _GNU_SOURCE
#include "config.h"
#include <glib.h>
#include <string.h>
#include <clutter/evdev/clutter-evdev.h>
#include "meta-surface-actor-wayland.h"
#include "meta-wayland-private.h"
struct _MetaWaylandTouchSurface
{
MetaWaylandSurface *surface;
MetaWaylandTouch *touch;
struct wl_listener surface_destroy_listener;
struct wl_list resource_list;
gint touch_count;
};
struct _MetaWaylandTouchInfo
{
MetaWaylandTouchSurface *touch_surface;
guint32 slot_serial;
gint32 slot;
gfloat x;
gfloat y;
guint updated : 1;
};
static void
move_resources (struct wl_list *destination, struct wl_list *source)
{
wl_list_insert_list (destination, source);
wl_list_init (source);
}
static void
move_resources_for_client (struct wl_list *destination,
struct wl_list *source,
struct wl_client *client)
{
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe (resource, tmp, source)
{
if (wl_resource_get_client (resource) == client)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_insert (destination, wl_resource_get_link (resource));
}
}
}
static void
touch_surface_free (gpointer data)
{
MetaWaylandTouchSurface *touch_surface = data;
MetaWaylandTouch *touch = touch_surface->touch;
move_resources (&touch->resource_list,
&touch_surface->resource_list);
wl_list_remove (&touch_surface->surface_destroy_listener.link);
g_free (touch_surface);
}
static MetaWaylandTouchSurface *
touch_surface_increment_touch (MetaWaylandTouchSurface *surface)
{
surface->touch_count++;
return surface;
}
static void
touch_surface_decrement_touch (MetaWaylandTouchSurface *touch_surface)
{
touch_surface->touch_count--;
if (touch_surface->touch_count == 0)
{
/* Now that there are no touches on the surface, free the
* MetaWaylandTouchSurface, the memory is actually owned by
* the touch_surface->touch_surfaces hashtable, so remove the
* item from there.
*/
MetaWaylandTouch *touch = touch_surface->touch;
g_hash_table_remove (touch->touch_surfaces, touch_surface->surface);
}
}
static void
touch_handle_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandTouchSurface *touch_surface = wl_container_of (listener, touch_surface, surface_destroy_listener);
MetaWaylandSurface *surface = touch_surface->surface;
MetaWaylandTouch *touch = touch_surface->touch;
MetaWaylandTouchInfo *touch_info;
GHashTableIter iter;
g_hash_table_iter_init (&iter, touch->touches);
/* Destroy all touches on the surface, this indirectly drops touch_count
* on the touch_surface to 0, also freeing touch_surface and removing
* from the touch_surfaces hashtable.
*/
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
{
if (touch_info->touch_surface == touch_surface)
g_hash_table_iter_remove (&iter);
}
/* Ensure the surface no longer exists */
g_assert (g_hash_table_remove (touch->touch_surfaces, surface) == FALSE);
}
static MetaWaylandTouchSurface *
touch_surface_get (MetaWaylandTouch *touch,
MetaWaylandSurface *surface)
{
MetaWaylandTouchSurface *touch_surface;
touch_surface = g_hash_table_lookup (touch->touch_surfaces, surface);
if (touch_surface)
return touch_surface_increment_touch (touch_surface);
/* Create a new one for this surface */
touch_surface = g_new0 (MetaWaylandTouchSurface, 1);
touch_surface->touch = touch;
touch_surface->surface = surface;
touch_surface->touch_count = 1;
touch_surface->surface_destroy_listener.notify = touch_handle_surface_destroy;
wl_resource_add_destroy_listener (touch_surface->surface->resource,
&touch_surface->surface_destroy_listener);
wl_list_init (&touch_surface->resource_list);
move_resources_for_client (&touch_surface->resource_list,
&touch->resource_list,
wl_resource_get_client (touch_surface->surface->resource));
g_hash_table_insert (touch->touch_surfaces, surface, touch_surface);
return touch_surface;
}
static MetaWaylandTouchInfo *
touch_get_info (MetaWaylandTouch *touch,
ClutterEventSequence *sequence,
gboolean create)
{
MetaWaylandTouchInfo *touch_info;
touch_info = g_hash_table_lookup (touch->touches, sequence);
if (!touch_info && create)
{
touch_info = g_new0 (MetaWaylandTouchInfo, 1);
touch_info->slot = clutter_evdev_event_sequence_get_slot (sequence);
g_hash_table_insert (touch->touches, sequence, touch_info);
}
return touch_info;
}
static void
touch_get_relative_coordinates (MetaWaylandTouch *touch,
MetaWaylandSurface *surface,
const ClutterEvent *event,
gfloat *x,
gfloat *y)
{
gfloat event_x, event_y;
clutter_event_get_coords (event, &event_x, &event_y);
if (surface->surface_actor)
{
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface->surface_actor),
event_x, event_y,
&event_x, &event_y);
}
*x = event_x;
*y = event_y;
}
void
meta_wayland_touch_update (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
sequence = clutter_event_get_event_sequence (event);
if (event->type == CLUTTER_TOUCH_BEGIN)
{
MetaWaylandSurface *surface = NULL;
ClutterActor *actor;
actor = clutter_event_get_source (event);
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
if (!surface)
return;
touch_info = touch_get_info (touch, sequence, TRUE);
touch_info->touch_surface = touch_surface_get (touch, surface);
}
else
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
if (event->type == CLUTTER_TOUCH_BEGIN ||
event->type == CLUTTER_TOUCH_END)
{
MetaWaylandSurface *surface = touch_info->touch_surface->surface;
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_display *display = wl_client_get_display (client);
touch_info->slot_serial = wl_display_next_serial (display);
}
touch_get_relative_coordinates (touch, touch_info->touch_surface->surface,
event, &touch_info->x, &touch_info->y);
touch_info->updated = TRUE;
}
static void
handle_touch_begin (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
struct wl_resource *resource;
struct wl_list *l;
sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
l = &touch_info->touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_down (resource, touch_info->slot_serial,
clutter_event_get_time (event),
touch_info->touch_surface->surface->resource,
touch_info->slot,
wl_fixed_from_double (touch_info->x),
wl_fixed_from_double (touch_info->y));
}
}
static void
handle_touch_update (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
struct wl_resource *resource;
struct wl_list *l;
sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
l = &touch_info->touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_motion (resource,
clutter_event_get_time (event),
touch_info->slot,
wl_fixed_from_double (touch_info->x),
wl_fixed_from_double (touch_info->y));
}
}
static void
handle_touch_end (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
struct wl_resource *resource;
struct wl_list *l;
sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
l = &touch_info->touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_up (resource, touch_info->slot_serial,
clutter_event_get_time (event),
touch_info->slot);
}
g_hash_table_remove (touch->touches, sequence);
}
static GList *
touch_get_surfaces (MetaWaylandTouch *touch,
gboolean only_updated)
{
MetaWaylandTouchInfo *touch_info;
GList *surfaces = NULL;
GHashTableIter iter;
g_hash_table_iter_init (&iter, touch->touches);
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
{
if (only_updated && !touch_info->updated)
continue;
if (g_list_find (surfaces, touch_info->touch_surface))
continue;
surfaces = g_list_prepend (surfaces, touch_info->touch_surface);
touch_info->updated = FALSE;
}
return g_list_reverse (surfaces);
}
static void
touch_send_frame_event (MetaWaylandTouch *touch)
{
GList *surfaces, *s;
surfaces = s = touch_get_surfaces (touch, TRUE);
for (s = surfaces; s; s = s->next)
{
MetaWaylandTouchSurface *touch_surface = s->data;
struct wl_resource *resource;
struct wl_list *l;
l = &touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_frame (resource);
}
}
g_list_free (surfaces);
}
static void
check_send_frame_event (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
gint32 slot;
sequence = clutter_event_get_event_sequence (event);
slot = clutter_evdev_event_sequence_get_slot (sequence);
touch->frame_slots &= ~(1 << slot);
if (touch->frame_slots == 0)
touch_send_frame_event (touch);
}
gboolean
meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
switch (event->type)
{
case CLUTTER_TOUCH_BEGIN:
handle_touch_begin (touch, event);
break;
case CLUTTER_TOUCH_UPDATE:
handle_touch_update (touch, event);
break;
case CLUTTER_TOUCH_END:
handle_touch_end (touch, event);
break;
default:
return FALSE;
}
check_send_frame_event (touch, event);
return FALSE;
}
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
touch_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_touch_interface touch_interface = {
touch_release,
};
static void
touch_info_free (MetaWaylandTouchInfo *touch_info)
{
touch_surface_decrement_touch (touch_info->touch_surface);
g_free (touch_info);
}
static gboolean
evdev_filter_func (struct libinput_event *event,
gpointer data)
{
MetaWaylandTouch *touch = data;
switch (libinput_event_get_type (event))
{
case LIBINPUT_EVENT_TOUCH_DOWN:
case LIBINPUT_EVENT_TOUCH_UP:
case LIBINPUT_EVENT_TOUCH_MOTION: {
struct libinput_event_touch *touch_event;
int32_t slot;
touch_event = libinput_event_get_touch_event (event);
slot = libinput_event_touch_get_slot (touch_event);
/* XXX: Could theoretically overflow, 64 slots should be
* enough for most hw/usecases though.
*/
touch->frame_slots |= (1 << slot);
break;
}
case LIBINPUT_EVENT_TOUCH_CANCEL:
/* Clutter translates this into individual CLUTTER_TOUCH_CANCEL events,
* which are not so useful when sending a global signal as the protocol
* requires.
*/
meta_wayland_touch_cancel (touch);
break;
default:
break;
}
return CLUTTER_EVENT_PROPAGATE;
}
void
meta_wayland_touch_init (MetaWaylandTouch *touch,
struct wl_display *display)
{
ClutterDeviceManager *manager;
memset (touch, 0, sizeof *touch);
touch->display = display;
touch->touch_surfaces = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) touch_surface_free);
touch->touches = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) touch_info_free);
wl_list_init (&touch->resource_list);
manager = clutter_device_manager_get_default ();
touch->device = clutter_device_manager_get_core_device (manager, CLUTTER_TOUCHSCREEN_DEVICE);
clutter_evdev_add_filter (evdev_filter_func, touch, NULL);
}
void
meta_wayland_touch_release (MetaWaylandTouch *touch)
{
clutter_evdev_remove_filter (evdev_filter_func, touch);
g_hash_table_unref (touch->touch_surfaces);
g_hash_table_unref (touch->touches);
}
void
meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id)
{
struct wl_resource *cr;
cr = wl_resource_create (client, &wl_touch_interface,
MIN (META_WL_TOUCH_VERSION, wl_resource_get_version (seat_resource)), id);
wl_resource_set_implementation (cr, NULL, touch, unbind_resource);
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
}
void
meta_wayland_touch_cancel (MetaWaylandTouch *touch)
{
GList *surfaces, *s;
surfaces = s = touch_get_surfaces (touch, FALSE);
while (s)
{
MetaWaylandTouchSurface *touch_surface = s->data;
struct wl_resource *resource;
struct wl_list *l;
l = &touch_surface->resource_list;
wl_resource_for_each(resource, l)
wl_touch_send_cancel (resource);
}
g_hash_table_remove_all (touch->touches);
g_list_free (surfaces);
}

View File

@@ -0,0 +1,64 @@
/*
* Wayland Support
*
* Copyright (C) 2014 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_TOUCH_H
#define META_WAYLAND_TOUCH_H
#include <wayland-server.h>
#include <glib.h>
#include "meta-wayland-types.h"
typedef struct _MetaWaylandTouchSurface MetaWaylandTouchSurface;
typedef struct _MetaWaylandTouchInfo MetaWaylandTouchInfo;
struct _MetaWaylandTouch
{
struct wl_display *display;
struct wl_list resource_list;
GHashTable *touch_surfaces; /* HT of MetaWaylandSurface->MetaWaylandTouchSurface */
GHashTable *touches; /* HT of sequence->MetaWaylandTouchInfo */
ClutterInputDevice *device;
guint64 frame_slots;
};
void meta_wayland_touch_init (MetaWaylandTouch *touch,
struct wl_display *display);
void meta_wayland_touch_release (MetaWaylandTouch *touch);
void meta_wayland_touch_update (MetaWaylandTouch *touch,
const ClutterEvent *event);
gboolean meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
const ClutterEvent *event);
void meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id);
void meta_wayland_touch_cancel (MetaWaylandTouch *touch);
#endif /* META_WAYLAND_TOUCH_H */

View File

@@ -29,6 +29,7 @@ typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;

View File

@@ -51,7 +51,7 @@
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_TOUCH_VERSION 3 /* from wl_seat */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */

View File

@@ -361,6 +361,8 @@ meta_window_wayland_move_resize (MetaWindow *window,
rect.width = width;
rect.height = height;
window->buffer_rect = rect;
if (rect.width != window->rect.width || rect.height != window->rect.height)
flags |= META_IS_RESIZE_ACTION;

1891
src/x11/events.c Normal file

File diff suppressed because it is too large Load Diff

36
src/x11/events.h Normal file
View File

@@ -0,0 +1,36 @@
/* -*- 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_X11_H
#define META_EVENTS_X11_H
void meta_display_init_events_x11 (MetaDisplay *display);
void meta_display_free_events_x11 (MetaDisplay *display);
void meta_display_events_x11_add_func (GFunc func,
gpointer user_data);
void meta_display_events_x11_remove_func (GFunc func,
gpointer user_data);
#endif

View File

@@ -20,11 +20,12 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "window-private.h"
#ifndef META_WINDOW_X11_PRIVATE_H
#define META_WINDOW_X11_PRIVATE_H
#include "window-private.h"
#include "ui/resizepopup.h"
G_BEGIN_DECLS
typedef struct _MetaWindowX11Private MetaWindowX11Private;
@@ -55,6 +56,10 @@ struct _MetaWindowX11Private
int border_width;
MetaResizePopup *grab_resize_popup;
/* These are in server coordinates. If we have a frame, it's
* relative to the frame. */
MetaRectangle client_rect;
};
G_END_DECLS

View File

@@ -204,14 +204,16 @@ send_configure_notify (MetaWindow *window)
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
XEvent event;
g_assert (!window->override_redirect);
/* from twm */
event.type = ConfigureNotify;
event.xconfigure.display = window->display->xdisplay;
event.xconfigure.event = window->xwindow;
event.xconfigure.window = window->xwindow;
event.xconfigure.x = window->rect.x - priv->border_width;
event.xconfigure.y = window->rect.y - priv->border_width;
event.xconfigure.x = priv->client_rect.x - priv->border_width;
event.xconfigure.y = priv->client_rect.y - priv->border_width;
if (window->frame)
{
if (window->withdrawn)
@@ -233,8 +235,8 @@ send_configure_notify (MetaWindow *window)
event.xconfigure.y += window->frame->rect.y;
}
}
event.xconfigure.width = window->rect.width;
event.xconfigure.height = window->rect.height;
event.xconfigure.width = priv->client_rect.width;
event.xconfigure.height = priv->client_rect.height;
event.xconfigure.border_width = priv->border_width; /* requested not actual */
event.xconfigure.above = None; /* FIXME */
event.xconfigure.override_redirect = False;
@@ -492,6 +494,7 @@ meta_window_apply_session_info (MetaWindow *window,
flags = META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
adjust_for_gravity (window, FALSE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
}
@@ -500,7 +503,6 @@ static void
meta_window_x11_manage (MetaWindow *window)
{
MetaDisplay *display = window->display;
MetaMoveResizeFlags flags;
meta_display_register_x_window (display, &window->xwindow, window);
meta_window_x11_update_shape_region (window);
@@ -518,6 +520,9 @@ meta_window_x11_manage (MetaWindow *window)
meta_window_x11_update_net_wm_type (window);
if (window->decorated)
meta_window_ensure_frame (window);
/* Now try applying saved stuff from the session */
{
const MetaWindowSessionInfo *info;
@@ -531,14 +536,26 @@ meta_window_x11_manage (MetaWindow *window)
}
}
/* Put our state back where it should be,
* passing TRUE for is_configure_request, ICCCM says
* initial map is handled same as configure request
/* For override-redirect windows, save the client rect
* directly. window->rect was assigned from the XWindowAttributes
* in the main meta_window_shared_new.
*
* For normal windows, do a full ConfigureRequest based on the
* window hints, as that's what the ICCCM says to do.
*/
flags = META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
if (!window->override_redirect)
if (window->override_redirect)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
}
else
{
MetaRectangle rect;
MetaMoveResizeFlags flags;
int gravity = window->size_hints.win_gravity;
rect.x = window->size_hints.x;
@@ -546,7 +563,10 @@ meta_window_x11_manage (MetaWindow *window)
rect.width = window->size_hints.width;
rect.height = window->size_hints.height;
flags = META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
adjust_for_gravity (window, TRUE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
}
@@ -633,17 +653,22 @@ meta_window_x11_unmanage (MetaWindow *window)
if (META_DISPLAY_HAS_SHAPE (window->display))
XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
/* The XReparentWindow call in meta_window_destroy_frame() moves the
* window so we need to send a configure notify; see bug 399552. (We
* also do this just in case a window got unmaximized.)
*/
send_configure_notify (window);
meta_window_ungrab_keys (window);
meta_display_ungrab_window_buttons (window->display, window->xwindow);
meta_display_ungrab_focus_window_button (window->display, window);
meta_error_trap_pop (window->display);
if (window->frame)
{
/* The XReparentWindow call in meta_window_destroy_frame() moves the
* window so we need to send a configure notify; see bug 399552. (We
* also do this just in case a window got unmaximized.)
*/
send_configure_notify (window);
meta_window_destroy_frame (window);
}
}
static void
@@ -785,6 +810,22 @@ meta_window_x11_focus (MetaWindow *window,
}
}
static void
meta_window_get_client_root_coords (MetaWindow *window,
MetaRectangle *rect)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
*rect = priv->client_rect;
if (window->frame)
{
rect->x += window->frame->rect.x;
rect->y += window->frame->rect.y;
}
}
static void
meta_window_refresh_resize_popup (MetaWindow *window)
{
@@ -888,8 +929,7 @@ sync_request_timeout (gpointer data)
* window updates
*/
window->sync_request_wait_serial = 0;
meta_compositor_set_updates_frozen (window->display->compositor, window,
meta_window_updates_are_frozen (window));
meta_compositor_sync_updates_frozen (window->display->compositor, window);
if (window == window->display->grab_window &&
meta_grab_op_is_resizing (window->display->grab_op))
@@ -952,8 +992,7 @@ send_sync_request (MetaWindow *window)
g_source_set_name_by_id (window->sync_request_timeout_id,
"[mutter] sync_request_timeout");
meta_compositor_set_updates_frozen (window->display->compositor, window,
meta_window_updates_are_frozen (window));
meta_compositor_sync_updates_frozen (window->display->compositor, window);
}
static unsigned long
@@ -1003,9 +1042,7 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
MetaFrameBorders borders;
int root_x_nw, root_y_nw;
int w, h;
int client_move_x, client_move_y;
MetaRectangle client_rect;
int size_dx, size_dy;
XWindowChanges values;
unsigned int mask;
@@ -1021,32 +1058,22 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0;
/* meta_window_constrain() might have maximized the window after placement,
* changing the borders.
*/
meta_frame_calc_borders (window->frame, &borders);
root_x_nw = constrained_rect.x;
root_y_nw = constrained_rect.y;
w = constrained_rect.width;
h = constrained_rect.height;
size_dx = constrained_rect.x - window->rect.width;
size_dy = constrained_rect.y - window->rect.height;
size_dx = w - window->rect.width;
size_dy = h - window->rect.height;
if (size_dx != 0 || size_dy != 0)
need_resize_client = TRUE;
window->rect.width = w;
window->rect.height = h;
window->rect = constrained_rect;
if (window->frame)
{
int new_w, new_h;
int new_x, new_y;
new_w = window->rect.width + borders.total.left + borders.total.right;
/* Compute new frame size */
new_w = window->rect.width + borders.invisible.left + borders.invisible.right;
new_h = borders.total.top + borders.total.bottom;
new_h = borders.invisible.top + borders.invisible.bottom;
if (!window->shaded)
new_h += window->rect.height;
@@ -1058,19 +1085,9 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
window->frame->rect.height = new_h;
}
meta_topic (META_DEBUG_GEOMETRY,
"Calculated frame size %dx%d\n",
window->frame->rect.width,
window->frame->rect.height);
}
if (window->frame)
{
int new_x, new_y;
/* Compute new frame coords */
new_x = root_x_nw - borders.total.left;
new_y = root_y_nw - borders.total.top;
new_x = window->rect.x - borders.invisible.left;
new_y = window->rect.y - borders.invisible.top;
if (new_x != window->frame->rect.x ||
new_y != window->frame->rect.y)
@@ -1079,22 +1096,35 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
window->frame->rect.x = new_x;
window->frame->rect.y = new_y;
}
client_move_x = borders.total.left;
client_move_y = borders.total.top;
}
else
/* Calculate the new client rect */
meta_window_frame_rect_to_client_rect (window, &constrained_rect, &client_rect);
/* The above client_rect is in root window coordinates. The
* values we need to pass to XConfigureWindow are in parent
* coordinates, so if the window is in a frame, we need to
* correct the x/y positions here. */
if (window->frame)
{
client_move_x = root_x_nw;
client_move_y = root_y_nw;
client_rect.x = borders.total.left;
client_rect.y = borders.total.top;
}
if (client_move_x != window->rect.x ||
client_move_y != window->rect.y)
if (client_rect.x != priv->client_rect.x ||
client_rect.y != priv->client_rect.y)
{
need_move_client = TRUE;
window->rect.x = client_move_x;
window->rect.y = client_move_y;
priv->client_rect.x = client_rect.x;
priv->client_rect.y = client_rect.y;
}
if (client_rect.width != priv->client_rect.width ||
client_rect.height != priv->client_rect.height)
{
need_resize_client = TRUE;
priv->client_rect.width = client_rect.width;
priv->client_rect.height = client_rect.height;
}
/* If frame extents have changed, fill in other frame fields and
@@ -1186,10 +1216,10 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
need_move_frame, need_resize_frame);
values.border_width = 0;
values.x = client_move_x;
values.y = client_move_y;
values.width = window->rect.width;
values.height = window->rect.height;
values.x = client_rect.x;
values.y = client_rect.y;
values.width = client_rect.width;
values.height = client_rect.height;
mask = 0;
if (is_configure_request && priv->border_width != 0)
@@ -1226,6 +1256,11 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
gravity,
need_move_frame, need_resize_frame);
if (window->frame)
window->buffer_rect = window->frame->rect;
else
window->buffer_rect = client_rect;
if (need_configure_notify)
send_configure_notify (window);
@@ -1768,6 +1803,8 @@ void
meta_window_x11_update_input_region (MetaWindow *window)
{
cairo_region_t *region = NULL;
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
/* Decorated windows don't have an input region, because
we don't shape the frame to match the client windows
@@ -1804,8 +1841,8 @@ meta_window_x11_update_input_region (MetaWindow *window)
(n_rects == 1 &&
(rects[0].x != 0 ||
rects[0].y != 0 ||
rects[0].width != window->rect.width ||
rects[0].height != window->rect.height)))
rects[0].width != priv->client_rect.width ||
rects[0].height != priv->client_rect.height)))
region = region_create_from_x_rectangles (rects, n_rects);
XFree (rects);
@@ -1818,8 +1855,8 @@ meta_window_x11_update_input_region (MetaWindow *window)
client_area.x = 0;
client_area.y = 0;
client_area.width = window->rect.width;
client_area.height = window->rect.height;
client_area.width = priv->client_rect.width;
client_area.height = priv->client_rect.height;
/* The shape we get back from the client may have coordinates
* outside of the frame. The X SHAPE Extension requires that
@@ -1850,6 +1887,8 @@ meta_window_set_shape_region (MetaWindow *window,
void
meta_window_x11_update_shape_region (MetaWindow *window)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
cairo_region_t *region = NULL;
if (META_DISPLAY_HAS_SHAPE (window->display))
@@ -1893,8 +1932,8 @@ meta_window_x11_update_shape_region (MetaWindow *window)
client_area.x = 0;
client_area.y = 0;
client_area.width = window->rect.width;
client_area.height = window->rect.height;
client_area.width = priv->client_rect.width;
client_area.height = priv->client_rect.height;
/* The shape we get back from the client may have coordinates
* outside of the frame. The X SHAPE Extension requires that
@@ -2072,14 +2111,41 @@ meta_window_move_resize_request (MetaWindow *window,
if (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION))
{
MetaRectangle rect;
MetaRectangle rect, monitor_rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
meta_screen_get_monitor_geometry (window->screen, window->monitor->number, &monitor_rect);
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly - don't get fooled by
* windows which hide their titlebar when maximized or which are
* client decorated; that's not the same as fullscreen, even
* if there are no struts making the workarea smaller than
* the monitor.
*/
if (meta_prefs_get_force_fullscreen() &&
!window->hide_titlebar_when_maximized &&
(window->decorated || !meta_window_is_client_decorated (window)) &&
meta_rectangle_equal (&rect, &monitor_rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
{
/*
meta_topic (META_DEBUG_GEOMETRY,
*/
meta_warning (
"Treating resize request of legacy application %s as a "
"fullscreen request\n",
window->desc);
meta_window_make_fullscreen_internal (window);
}
adjust_for_gravity (window, TRUE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
}
@@ -3146,7 +3212,7 @@ meta_window_x11_recalc_window_type (MetaWindow *window)
*/
if (window->override_redirect)
{
switch (window->type)
switch (type)
{
/* Decorated types */
case META_WINDOW_NORMAL:
@@ -3191,6 +3257,9 @@ void
meta_window_x11_configure_notify (MetaWindow *window,
XConfigureEvent *event)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
g_assert (window->override_redirect);
g_assert (window->frame == NULL);
@@ -3198,7 +3267,11 @@ meta_window_x11_configure_notify (MetaWindow *window,
window->rect.y = event->y;
window->rect.width = event->width;
window->rect.height = event->height;
meta_window_update_monitor (window);
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
meta_window_update_monitor (window, FALSE);
/* Whether an override-redirect window is considered fullscreen depends
* on its geometry.
@@ -3380,8 +3453,7 @@ meta_window_x11_update_sync_request_counter (MetaWindow *window,
}
window->sync_request_serial = new_counter_value;
meta_compositor_set_updates_frozen (window->display->compositor, window,
meta_window_updates_are_frozen (window));
meta_compositor_sync_updates_frozen (window->display->compositor, window);
if (window == window->display->grab_window &&
meta_grab_op_is_resizing (window->display->grab_op) &&
@@ -3416,3 +3488,9 @@ meta_window_x11_update_sync_request_counter (MetaWindow *window,
meta_compositor_queue_frame_drawn (window->display->compositor, window,
no_delay_frame);
}
Window
meta_window_x11_get_toplevel_xwindow (MetaWindow *window)
{
return window->frame ? window->frame->xwindow : window->xwindow;
}

View File

@@ -73,4 +73,6 @@ gboolean meta_window_x11_client_message (MetaWindow *window,
void meta_window_x11_configure_notify (MetaWindow *window,
XConfigureEvent *event);
Window meta_window_x11_get_toplevel_xwindow (MetaWindow *window);
#endif