Compare commits

..

17 Commits

Author SHA1 Message Date
Jasper St. Pierre
531a7b2812 wayland: Support alternative focus modes like focus-follows-mouse
Use the existing code for MetaWindow focus-follows-mouse to support this.
2013-11-02 12:53:32 -04:00
Jasper St. Pierre
580669cdea display: Use MetaWindow for auto-raise callbacks
This allows us to autoraise Wayland windows... well, except for the
XQueryPointer, but we'll replace that soon.
2013-11-02 12:53:31 -04:00
Jasper St. Pierre
e50a578ad3 display: Invoke Wayland from the Grand Central Station callback 2013-11-02 12:53:31 -04:00
Jasper St. Pierre
06b3d36e97 wayland: Move cursor tracker handling code to meta_wayland_seat_handle_event 2013-11-02 12:53:31 -04:00
Jasper St. Pierre
715fa91599 wayland: Drop raise on click too
We'll handle this through GCD as well.
2013-11-02 12:53:31 -04:00
Jasper St. Pierre
997188e914 wayland: Drop focus on click
The native raise-on-click works with Wayland clients through the standard
Grand Central Station event handling, with MetaWindow.
2013-11-02 12:53:31 -04:00
Jasper St. Pierre
c6dd56f9ce wayland: Drop old hack to synthesize motion events
mutter now uses Clutter events for the source of its drag support, so
we don't need to synthesize X11 events anymore.
2013-11-02 12:53:31 -04:00
Jasper St. Pierre
466af03ed3 keybindings: Port to Clutter 2013-11-02 12:53:31 -04:00
Neil Roberts
9c2d806556 wayland: Use an event filter instead of the captured event signal
In order to see all Clutter events, Mutter was previously installing a
signal handler on the ‘captured-event’ signal on the stage and
additionally using a signal emission hook to cope with grabs. This
changes it to use the new clutter_event_add_filter API so that we can
avoid the signal emission hook hack.
2013-11-02 12:53:31 -04:00
Jasper St. Pierre
13a7c8da85 display: Move the pointer event handling code to work in terms of Clutter events
There is now a meta_display_handle_event alongside the
meta_display_handle_xevent function which handles events in terms of
Clutter events instead of X events. A Clutter event filter is
registered so that all Clutter events will pass through this function.
The pointer event handling code from the X event version has been moved
into this new function and has been modified to use the details from
the Clutter event instead of the X event. This is a step towards
moving all of the event handling code over to use Clutter events.

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

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

https://bugzilla.gnome.org/show_bug.cgi?id=707446
2013-11-02 12:35:58 -04:00
191 changed files with 13952 additions and 9882 deletions

6
.gitignore vendored
View File

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

41
COPYING
View File

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

83
NEWS
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "clutter-utils.h"
@@ -93,10 +95,8 @@ meta_actor_vertices_are_untransformed (ClutterVertex *verts,
v3x != v1x || v3y != v2y)
return FALSE;
if (x_origin)
*x_origin = x;
if (y_origin)
*y_origin = y;
*x_origin = x;
*y_origin = y;
return TRUE;
}

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_CLUTTER_UTILS_H__

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <clutter/clutter.h>

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_COGL_UTILS_H__

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**

View File

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

View File

@@ -1,66 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Ray Strode <rstrode@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_CULLABLE_H__
#define __META_CULLABLE_H__
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define META_TYPE_CULLABLE (meta_cullable_get_type ())
#define META_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CULLABLE, MetaCullable))
#define META_IS_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CULLABLE))
#define META_CULLABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_CULLABLE, MetaCullableInterface))
typedef struct _MetaCullable MetaCullable;
typedef struct _MetaCullableInterface MetaCullableInterface;
struct _MetaCullableInterface
{
GTypeInterface g_iface;
void (* cull_out) (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void (* reset_culling) (MetaCullable *cullable);
};
GType meta_cullable_get_type (void);
void meta_cullable_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void meta_cullable_reset_culling (MetaCullable *cullable);
/* Utility methods for implementations */
void meta_cullable_cull_out_children (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void meta_cullable_reset_culling_children (MetaCullable *cullable);
G_END_DECLS
#endif /* __META_CULLABLE_H__ */

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <meta/meta-plugin.h>

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_MODULE_H_

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
@@ -324,59 +326,3 @@ meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
else
return meta_plugin_complete_display_change (plugin, TRUE);
}
gboolean
meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
if (klass->show_tile_preview)
{
klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number);
return TRUE;
}
return FALSE;
}
gboolean
meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
if (klass->hide_tile_preview)
{
klass->hide_tile_preview (plugin);
return TRUE;
}
return FALSE;
}
void
meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
MetaWindow *window)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return;
if (klass->show_window_menu)
klass->show_window_menu (plugin, window);
}

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_PLUGIN_MANAGER_H_
@@ -75,13 +77,4 @@ gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin,
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number);
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
MetaWindow *window);
#endif

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**
@@ -30,7 +32,6 @@
#include "meta-plugin-manager.h"
#include <meta/screen.h>
#include <meta/display.h>
#include <meta/util.h>
#include <string.h>
#include <X11/Xlib.h>

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__

View File

@@ -13,7 +13,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**

View File

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

View File

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

View File

@@ -1,164 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-wayland.h"
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
#include "meta-wayland-private.h"
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
MetaWaylandBuffer *buffer;
};
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
static void
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
struct wl_resource *resource = priv->buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
}
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
{
/* XXX -- look at the SHM buffer format. */
return TRUE;
}
static gboolean
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
{
/* TODO: ensure that the buffer isn't NULL, implement
* wayland mapping semantics */
return TRUE;
}
static gboolean
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
{
return FALSE;
}
static void
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
/* Do nothing. In the future, we'll use KMS to set this
* up as a hardware overlay or something. */
}
static gboolean
meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
{
return FALSE;
}
static MetaWindow *
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
return priv->surface->window;
}
static void
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
{
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
}
static void
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
{
}
MetaSurfaceActor *
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
{
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
g_assert (meta_is_wayland_compositor ());
priv->surface = surface;
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
priv->buffer = buffer;
if (buffer)
meta_shaped_texture_set_texture (stex, buffer->texture);
else
meta_shaped_texture_set_texture (stex, NULL);
}
MetaWaylandSurface *
meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
return priv->surface;
}

View File

@@ -1,66 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
#define __META_SURFACE_ACTOR_WAYLAND_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include "meta-wayland.h"
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
struct _MetaSurfaceActorWayland
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorWaylandClass
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_wayland_get_type (void);
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */

View File

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

View File

@@ -1,69 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_X11_H__
#define __META_SURFACE_ACTOR_X11_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include <X11/extensions/Xdamage.h>
#include <meta/display.h>
#include <meta/window.h>
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
struct _MetaSurfaceActorX11
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorX11Class
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_x11_get_type (void);
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_X11_H__ */

View File

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

View File

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

View File

@@ -18,7 +18,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
@@ -26,6 +28,41 @@
#include <clutter/clutter.h>
#include "meta-texture-rectangle.h"
CoglTexture *
meta_texture_rectangle_new (unsigned int width,
unsigned int height,
CoglPixelFormat format,
CoglPixelFormat internal_format,
unsigned int rowstride,
const guint8 *data,
GError **error)
{
ClutterBackend *backend =
clutter_get_default_backend ();
CoglContext *context =
clutter_backend_get_cogl_context (backend);
CoglTextureRectangle *tex_rect;
tex_rect = cogl_texture_rectangle_new_with_size (context,
width, height,
internal_format,
error);
if (tex_rect == NULL)
return NULL;
if (data)
cogl_texture_set_region (COGL_TEXTURE (tex_rect),
0, 0, /* src_x/y */
0, 0, /* dst_x/y */
width, height, /* dst_width/height */
width, height, /* width/height */
format,
rowstride,
data);
return COGL_TEXTURE (tex_rect);
}
static void
texture_rectangle_check_cb (CoglTexture *sub_texture,
const float *sub_texture_coords,

View File

@@ -18,7 +18,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_TEXTURE_RECTANGLE_H__
@@ -28,6 +30,15 @@
G_BEGIN_DECLS
CoglTexture *
meta_texture_rectangle_new (unsigned int width,
unsigned int height,
CoglPixelFormat format,
CoglPixelFormat internal_format,
unsigned int rowstride,
const guint8 *data,
GError **error);
gboolean
meta_texture_rectangle_check (CoglTexture *texture);

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <math.h>
@@ -355,10 +357,18 @@ texture_tower_create_texture (MetaTextureTower *tower,
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
meta_texture_rectangle_check (tower->textures[level - 1]))
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *context = clutter_backend_get_cogl_context (backend);
tower->textures[level] = cogl_texture_rectangle_new_with_size (context, width, height);
tower->textures[level] =
meta_texture_rectangle_new (width, height,
/* data format */
TEXTURE_FORMAT,
/* internal cogl format */
TEXTURE_FORMAT,
/* rowstride */
width * 4,
/* data */
NULL,
/* error */
NULL);
}
else
{

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_TEXTURE_TOWER_H__

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <string.h>

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_WINDOW_SHAPE_H__

View File

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

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "region-utils.h"

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_REGION_UTILS_H__

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/* The standard cycle-windows keybinding should be the key above the

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/*

View File

@@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <X11/Xlib.h>

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_BOXES_PRIVATE_H

View File

@@ -25,7 +25,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "boxes-private.h"

View File

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

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_CONSTRAINTS_H
@@ -38,6 +40,7 @@ typedef enum
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,

View File

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

View File

@@ -17,7 +17,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_CORE_H
@@ -159,8 +161,15 @@ const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
void meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,
int root_x,
int root_y,
int button,
guint32 timestamp);
void meta_core_get_menu_accelerator (MetaMenuOp menu_op,
int workspace,
unsigned int *keysym,
MetaVirtualModifier *modifiers);
gboolean meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,

View File

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

View File

@@ -19,7 +19,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_DISPLAY_PRIVATE_H
@@ -55,9 +57,10 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
guint32 timestamp,
gpointer user_data);
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
guint32 timestamp,
gpointer user_data);
typedef enum {
META_LIST_DEFAULT = 0, /* normal windows */
@@ -84,6 +87,14 @@ typedef enum {
META_TILE_MAXIMIZED
} MetaTileMode;
typedef enum {
META_FOCUS_NONE = 0,
META_FOCUS_X_CLIENT = 1,
META_FOCUS_WAYLAND_CLIENT = 2,
META_FOCUS_NO_FOCUS_WINDOW = 3,
META_FOCUS_STAGE = 4
} MetaFocusType;
struct _MetaDisplay
{
GObject parent_instance;
@@ -91,8 +102,6 @@ struct _MetaDisplay
char *name;
Display *xdisplay;
int clutter_event_filter;
Window leader_window;
Window timestamp_pinging_window;
@@ -117,6 +126,7 @@ struct _MetaDisplay
* like the no_focus_window or the stage X window. */
Window focus_xwindow;
gulong focus_serial;
MetaFocusType focus_type;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
@@ -138,14 +148,6 @@ struct _MetaDisplay
*/
guint allow_terminal_deactivation : 1;
/* If true, server->focus_serial refers to us changing the focus; in
* this case, we can ignore focus events that have exactly focus_serial,
* since we take care to make another request immediately afterwards.
* But if focus is being changed by another client, we have to accept
* multiple events with the same serial.
*/
guint focused_by_us : 1;
guint static_gravity_works : 1;
/*< private-ish >*/
@@ -215,6 +217,7 @@ struct _MetaDisplay
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time;
guint32 grab_motion_notify_time;
GList* grab_old_window_stacking;
MetaEdgeResistanceData *grab_edge_resistance_data;
unsigned int grab_last_user_action_was_snap;
@@ -232,8 +235,8 @@ struct _MetaDisplay
int grab_resize_timeout_id;
/* Keybindings stuff */
GHashTable *key_bindings;
GHashTable *key_bindings_index;
MetaKeyBinding *key_bindings;
int n_key_bindings;
int min_keycode;
int max_keycode;
KeySym *keymap;
@@ -263,6 +266,10 @@ struct _MetaDisplay
/* Managed by group.c */
GHashTable *groups_by_leader;
/* currently-active window menu if any */
MetaWindowMenu *window_menu;
MetaWindow *window_with_menu;
/* Managed by window-props.c */
MetaWindowPropHooks *prop_hooks_table;
GHashTable *prop_hooks;
@@ -439,13 +446,14 @@ void meta_display_retheme_all (void);
void meta_display_set_cursor_theme (const char *theme,
int size);
void meta_display_ping_window (MetaWindow *window,
void meta_display_ping_window (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp,
MetaWindowPingFunc ping_reply_func,
MetaWindowPingFunc ping_timeout_func,
void *user_data);
void meta_display_pong_for_serial (MetaDisplay *display,
guint32 serial);
gboolean meta_display_window_has_pending_pings (MetaDisplay *display,
MetaWindow *window);
int meta_resize_gravity_from_grab_op (MetaGrabOp op);
@@ -474,14 +482,21 @@ gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
gboolean meta_display_handle_xevent (MetaDisplay *display,
XEvent *event);
gboolean meta_display_handle_event (MetaDisplay *display,
const ClutterEvent *event);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event);
#endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
Window window,
guint32 timestamp);
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp);
#endif

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_EDGE_RESISTANCE_H

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**

View File

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

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_FRAME_PRIVATE_H
@@ -39,17 +41,15 @@ struct _MetaFrame
*/
MetaRectangle rect;
MetaFrameBorders cached_borders; /* valid if borders_cached is set */
/* position of client, size of frame */
int child_x;
int child_y;
int right_width;
int bottom_height;
guint mapped : 1;
guint need_reapply_frame_shape : 1;
guint is_flashing : 1; /* used by the visual bell flash */
guint borders_cached : 1;
};
void meta_window_ensure_frame (MetaWindow *window);
@@ -68,8 +68,6 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
gboolean need_move,
gboolean need_resize);
void meta_frame_clear_cached_borders (MetaFrame *frame);
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
void meta_frame_get_mask (MetaFrame *frame,

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_GROUP_PRIVATE_H

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_GROUP_PROPS_H

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_ICON_CACHE_H

View File

@@ -21,7 +21,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_KEYBINDINGS_PRIVATE_H
@@ -30,7 +32,6 @@
#include <gio/gio.h>
#include <meta/keybindings.h>
typedef struct _MetaKeyHandler MetaKeyHandler;
struct _MetaKeyHandler
{
char *name;
@@ -48,48 +49,9 @@ struct _MetaKeyBinding
KeyCode keycode;
unsigned int mask;
MetaVirtualModifier modifiers;
gint flags;
MetaKeyHandler *handler;
};
/**
* MetaKeyCombo:
* @keysym: keysym
* @keycode: keycode
* @modifiers: modifiers
*/
typedef struct _MetaKeyCombo MetaKeyCombo;
struct _MetaKeyCombo
{
unsigned int keysym;
unsigned int keycode;
MetaVirtualModifier modifiers;
};
typedef struct
{
char *name;
GSettings *settings;
MetaKeyBindingAction action;
/*
* A list of MetaKeyCombos. Each of them is bound to
* this keypref. If one has keysym==modifiers==0, it is
* ignored.
*/
GSList *combos;
/* for keybindings that can have shift or not like Alt+Tab */
gboolean add_shift:1;
/* for keybindings that apply only to a window */
gboolean per_window:1;
/* for keybindings not added with meta_display_add_keybinding() */
gboolean builtin:1;
} MetaKeyPref;
void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
@@ -117,8 +79,5 @@ gboolean meta_prefs_add_keybinding (const char *name,
gboolean meta_prefs_remove_keybinding (const char *name);
GList *meta_prefs_get_keybindings (void);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void);
#endif

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
@@ -29,21 +31,18 @@
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_revert_root (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
void meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage);
#endif

View File

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

View File

@@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c

View File

@@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
@@ -535,7 +537,7 @@ make_watch (MetaIdleMonitor *monitor,
watch->timeout_source = source;
}
}
else if (monitor->user_active_alarm != None)
else
{
if (timeout_msec != 0)
{
@@ -653,10 +655,8 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
{
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
g_object_ref (monitor);
g_hash_table_remove (monitor->watches,
GUINT_TO_POINTER (id));
g_object_unref (monitor);
}
/**
@@ -949,8 +949,6 @@ on_bus_acquired (GDBusConnection *connection,
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_slist_free (devices);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",

View File

@@ -13,7 +13,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)

View File

@@ -20,7 +20,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/*
@@ -815,22 +817,6 @@ meta_monitor_config_match_current (MetaMonitorConfig *self,
return ok;
}
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
unsigned int i;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
if (outputs[i].hotplug_mode_update)
return TRUE;
return FALSE;
}
static MetaConfiguration *
meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaOutput *outputs,

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"

View File

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

View File

@@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_PLACE_H
@@ -26,6 +28,7 @@
#include "frame.h"
void meta_window_place (MetaWindow *window,
MetaFrameBorders *borders,
int x,
int y,
int *new_x,

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>

View File

@@ -23,7 +23,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_SESSION_H

View File

@@ -29,7 +29,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
@@ -1041,7 +1043,7 @@ stack_tracker_event_received (MetaStackTracker *tracker,
if (op->any.serial < tracker->xserver_serial)
{
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
g_warning ("Spurious X event received affecting stack; doing full re-query");
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;

View File

@@ -28,7 +28,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_STACK_TRACKER_H

View File

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

View File

@@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_STACK_H

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