Compare commits

...

101 Commits

Author SHA1 Message Date
b9d798c213 cursor-tracker: Properly handle invisible cursors
We might be asked to not display the cursor ourselves but we should
still emit cursor-changed signals and hand out the correct sprite and
hot point information when asked so that consumers can still draw an
updated cursor themselves.

This fixes the cursor not showing up in gnome-shell's zoom mode.
2014-04-07 19:23:35 +02:00
5abf41ab5a split cursor_tracker 2014-04-07 19:20:14 +02:00
4f609dbf5e xwayland: Don't use glib after forking
glib doesn't have any guarantee about working after forking.
We can get away with it, but we're better off just not using it.
2014-04-02 13:04:31 -04:00
2a7d12ba14 xwayland: Make failing to exec a fatal error 2014-04-02 13:03:29 -04:00
c4c0b5f0ab xwayland: Detect a fail to fork 2014-04-02 13:03:17 -04:00
8373c90cd8 background: Remove load_still_frame
Nothing uses it, and it's incompatible with XWayland anyway.
2014-04-02 12:35:24 -04:00
eb5b54dd8b xwayland: Split another part of the initialization sequence out
This will be used from a SIGUSR1 handler.
2014-04-02 11:41:28 -04:00
9653b79a35 xwayland: Split a helper out
This will make the next commit, which ports to the new ClientMessage
API, more understandable.
2014-04-02 11:41:28 -04:00
e07bd15fc2 xwayland: Make file cosmetically modern
Put a modeline, include "config.h", and shift around the include ordering
2014-04-02 11:41:27 -04:00
5cf0740b4e xwayland: Fork the X server ourselves
gspawn just isn't us the fine-grained control we need for starting
processes and leaking file descriptors in.
2014-04-02 11:41:27 -04:00
c540ddf59b xwayland: Move display_name into choose_xdisplay 2014-04-02 11:41:27 -04:00
a44295599c xwayland: Split out the code that creates the XWayland sockets 2014-04-02 11:41:26 -04:00
af272f2685 xwayland: Move global initialization down 2014-04-02 11:41:26 -04:00
81d033ec73 xwayland: Use %m instead of manual strerror(errno) 2014-04-02 11:41:26 -04:00
e9ee984921 wayland: Rename the wl_surface interface handlers
We usually name the method handlers after the direct name
of the interface methods. Do that for wl_surface as well.
2014-04-02 11:41:26 -04:00
3c404c5db3 wayland: Replace make_toplevel / window_unmanaging with set_window
The make_toplevel / window_unmanaging interface has never made
a lot of sense to me. Replace it with set_window, which does
effectively the same thing.

It's still not perfect in the case of XWayland, but I don't think
XWayland will ever make me happy.
2014-04-02 11:41:07 -04:00
e4cd000cef wayland: Implement wl_seat v3
The new XWayland DDX flat out requires seat v3.
2014-04-02 11:40:40 -04:00
6296fefea6 window-actor: Clean up has_shadow
This has some particularly picky #if 0'd code. Since the history for
it isn't illuminating in the slightest, I'm just going to kill it.
2014-04-02 11:40:04 -04:00
c1e3a6b742 idle-monitor: Actually get the check for is_wayland_compositor correctly
If we're a Wayland compositor we shouldn't be taking this path, ever.
2014-04-01 16:05:53 -04:00
dcd83b7365 idle-monitor-native: Remove another copy/paste error
Don't overwrite the watch with a new malloc'd variable.
2014-04-01 16:01:06 -04:00
617b00dfbd idle-monitor-native: Reindent 2014-04-01 15:52:11 -04:00
94692414cb idle-monitor-native: Fix copy/paste bug 2014-04-01 15:52:11 -04:00
ab6bc76bfd Move edid-parse to backends/ 2014-04-01 14:35:04 -04:00
57803f1d59 wayland-stage: Clean up and rename
It should be META_TYPE_WAYLAND_STAGE, not META_WAYLAND_TYPE_STAGE.

Well, actually, it *should* be META_TYPE_NATIVE_STAGE, because it's
not related to Wayland at all. But that comes later :)
2014-04-01 14:04:58 -04:00
67b6737b27 backend: Fix warning 2014-04-01 14:04:53 -04:00
29396014fd backend: Fix the nested mode 2014-04-01 13:56:40 -04:00
899d4d8477 monitor-manager: Move default get_edid_file / read_edid to base class
These are also used by the native manager.
2014-04-01 10:24:34 -04:00
f1c7063ee7 configure: Clean up old status line
While I'm here, I might as well. We rely on Xcursor now.
2014-03-31 23:48:59 -04:00
216ff7ebe5 Update .gitignore
It seems the new automake likes to litter these files all around.
2014-03-31 23:47:40 -04:00
34cc5efb90 configure: Add on subdir-objects
To stop automake from complaining
2014-03-31 23:47:11 -04:00
bce1d5117b Start creating different subdirectories for each backend 2014-03-31 23:44:47 -04:00
d5552cc372 Rename meta-xrandr-shared to meta-display-config-shared 2014-03-31 23:44:47 -04:00
fd392cc1e7 Remove "xrandr" from the name of the generated DBus files
It's about generic display config, not XRandR specifically.
2014-03-31 23:44:47 -04:00
b641d9d5a8 Rename the DBus interface files 2014-03-31 23:44:46 -04:00
5bcc78498f Move MetaLauncher to meta-backend 2014-03-31 23:44:46 -04:00
521125b672 meta-wayland: Use meta_clutter_init 2014-03-31 23:44:45 -04:00
89b931435d Move meta_clutter_init into a new file
We'll use this to get the initialization between the Wayland and
X11 compositor codepaths back in sync.
2014-03-31 23:44:25 -04:00
e22e9f5df5 main: Refactor some code slightly 2014-03-31 22:55:13 -04:00
20547e3b63 Move weston-launch to backends/
It's about display servers, not Wayland integration.
2014-03-31 22:48:34 -04:00
2cf185b4e4 Move mutter-Xatomtype to x11/ 2014-03-31 22:13:12 -04:00
229360b248 Start molding out a new src/backends/ dir
Right now this just has all of the files in one directory. We'll
be introducing more structure to this in the future, and build
a proper backend system.
2014-03-31 22:11:00 -04:00
ccced506ed Rename monitor => meta-monitor-manager 2014-03-31 22:05:24 -04:00
28b9160c01 Rename monitor-config => meta-monitor-config 2014-03-31 22:05:22 -04:00
ba6584a0d7 Move monitor-config to its own header file 2014-03-31 22:04:38 -04:00
2a0289a216 Move the dummy monitor manager to his own subclass / file 2014-03-31 21:52:32 -04:00
f6a73bcf22 cursor: Do less work if we don't have a connection to GBM at all 2014-03-31 19:14:56 -04:00
59e064f610 cursor: Split out code that loads an image into a GBM buffer 2014-03-31 19:14:56 -04:00
ba131626c2 cursor: Always use cogl_wayland_texture_2d_new_from_buffer
It makes our life so much easier.
2014-03-31 19:14:56 -04:00
30ebf46aa4 cursor: Reindent 2014-03-31 19:14:56 -04:00
da27735265 cursor: Refactor code to load cursor images out
We're going to make MetaCursorReference specialized and per-backend soon.
2014-03-31 19:14:55 -04:00
78dbf8cb56 cursor: Split out the structure for the actual textures / buffers out
This will allow us to have a MetaCursorReference 'subclass' that's
lazily loaded. We currently always load all the images.

The long-term plan is to have a subclass for each "backend" and only
have CoglTexture as a common denominator. For the nested X11 backend,
we use XDefineCursor on our stage window. For the Wayland backend, we
would use set_cursor on our stage surface. For the native backend, we
would use the GBM code that's there right now.

The CoglTexture is there to be a "shared fallback" between all devices,
and also for the get_sprite API.

The odd man out is the X11 compositor case. For that, we need to move
the responsibility of setting the final cursor image out of
MetaCursorTracker, and simply have it be about tracking the used sprite
image and pointer position.
2014-03-31 19:09:08 -04:00
f4e299ca46 cursor: Split out code that frees the MetaCursorReference 2014-03-31 18:27:20 -04:00
f95f2b0c6d cursor-tracker: Make set_root_cursor take a MetaCursorReference 2014-03-31 18:27:20 -04:00
fe42a4eb4e screen: Move XDefineCursor on the root window here
This is really an X11 front-end thing, so it doesn't belong in the
cursor tracker, which is a back-end thing.
2014-03-31 18:27:20 -04:00
565883dadb screen: Refactor update_cursor a bit 2014-03-31 18:27:19 -04:00
be60e4f6e7 cursor-tracker: Make set_window_cursor take a MetaCursorReference as well 2014-03-31 18:27:19 -04:00
fa60824096 cursor-tracker: Make set_grab_cursor take a MetaCursorReference 2014-03-31 18:27:19 -04:00
0efb0b47eb cursor: Move cursor caching layer to meta_cursor_reference_from_theme 2014-03-31 18:27:18 -04:00
0f810a4e21 cursor: Refactor out code that loads from XcursorImage 2014-03-31 18:27:18 -04:00
383d4c7e4e cursor: Introduce accessors for the texture / GBM bo
We want to make this private, and have MetaCursorReference be
backend-defined, with the texture possibly loaded on demand.

We can't make the definition of MetaCursorReference truly private yet
because of the XFixes cursor. A victim of MetaCursorTracker trying to
do too many things at once...
2014-03-31 18:27:18 -04:00
21425b5833 cursor-tracker: Split the code that loads MetaCursorReferences out
The plan here is to move the usage of these interfaces to the consumer,
and then slam the code into backends.
2014-03-31 18:27:18 -04:00
863569b702 cursor-tracker: Split out the code that updates the new cursor 2014-03-31 18:27:17 -04:00
5f52f55916 cursor-tracker: Start moving some code to a new file
I want the MetaCursorTracker to mostly be about retrieving cursor
information. Start moving the code that loads cursor images to a
new file, MetaCursor. Eventually, MetaCursorTracker's APIs will
all take MetaCursorReferences, and we can have a clean backend
split here.
2014-03-31 18:27:17 -04:00
0aec98cf02 idle-monitor: Hack out assert fail
It seems that we're getting XSyncAlarmNotify events here as a Wayland
compositor for some reason. Just hack this one out for now.
2014-03-31 18:27:17 -04:00
b64d14ff4a cursor-tracker: Rearrange code
Move take_texture closer to where it's used, and add hot_x / hot_y args.
2014-03-31 15:22:31 -04:00
08a8254deb cursor-tracker: Move ref_count to the top 2014-03-31 15:22:31 -04:00
11de01741c cursor-tracker: Add a comment about what previous is
It confused me a bit.
2014-03-31 15:22:31 -04:00
a7ea2cd365 cursor-tracker: Shadowing is bad, don't do it 2014-03-31 15:22:31 -04:00
a15a4faff0 cursor-tracker: Remove unused constants 2014-03-31 15:22:30 -04:00
b93176d89a cursor-tracker: Kill off an unused include 2014-03-30 23:06:01 -04:00
f842ea6d15 idle-monitor: Make the rest of the implementation-specific fields private 2014-03-30 23:04:39 -04:00
422f2e5fe6 idle-monitor: Kill off an unused field 2014-03-30 23:00:10 -04:00
3961f291e4 idle-monitor: Move the alarms field to the XSync backend
For whatever reason, this hash table was in the generic
implementation section instead of the XSync implementation,
even though it's only used by the XSync implementation.

Use it as a first pass of things to move over.
2014-03-30 22:55:54 -04:00
61d8b35254 idle-monitor: Move watch implementations to be private to the subclass 2014-03-30 22:55:03 -04:00
78457cf7b4 idle-monitor: Create separate subtypes for backend-specific idle monitors
The separation here isn't 100% clean yet, as there's common
parts that are still protocol specific. We'll clean that up
in the next commit.
2014-03-30 22:55:03 -04:00
1e2bdcc3c5 idle-monitor: Move reset_idletime handling to events.c
It's not specific to the Wayland protocol at all, and it's not really
a Wayland compositor thing. This should eventually be in the native
backend.
2014-03-30 22:55:02 -04:00
490e1c8c3b idle-monitor: Split the DBus implementation to a separate file 2014-03-30 22:55:02 -04:00
9a751a95e3 idle-monitor: Rearrange code to make it a cleaner split
We're going to push this to be subclasses soon.
2014-03-30 22:55:02 -04:00
afce448281 Kill meta_ui_add_event_func / remove_event_func
The reason we don't simply use gdk_window_add_filter directly is
because of some twisted idea that any GDK symbol being used from
core/ is a layer violation. While we certainly want to keep any
serious GDK code out of ui/, event handling is quite important
to have in core/, so simply use a GDK event filter directly.
2014-03-30 22:55:01 -04:00
b2405b701a Move monitor manager headers to their own files
Instead of having them in monitor-private.h.

This way, it's easier to move our own backend when the chance arises.
2014-03-30 22:54:52 -04:00
390c028da7 Rename the monitor backend filenames
To match the "meta-*" new-style naming.
2014-03-30 20:21:39 -04:00
82e02e39d3 window-actor: Fix the input shape region for decorated X11 windows
The code here before was completely wrong. Not only did it mix up
coordinate spaces of "client rect" vs. "frame rect", but it used
meta_frame_get_frame_bounds, which is specifically for the *visible*
bounds of a window!

In the case that we don't have a bounding or input shape region at
all on the client window, the input shape that we should apply is
the surface's natural shape. So, set the region to NULL to get the
natural rect picking semantics.
2014-03-30 20:16:58 -04:00
0f9b29b140 display: Don't double-free the screen
We already free the screen once in meta_display_close.

This fixes a crash when trying to restart mutter.
2014-03-28 13:58:50 -04:00
b367965f6c window: Track known_to_compositor and visible_to_compositor separately
Really, visible_to_compositor means that the window is shown, e.g.
not minimized. We need to be using a boolean tracking whether we've
called meta_compositor_add_window / meta_compositor_remove_window.

This fixes a jump during window placement when a window appears.
2014-03-28 13:52:59 -04:00
ed9dbf6aa2 window: Ensure that visible_to_compositor is set when unmanaging
visible_to_compositor should always be in sync with show_window /
hide_window calls, even when unmananging.

This fixes a crash where we call sync_window_state when the window
is unmanaging, since we use visible_to_compositor to determine whether
the compositor will crash.

This is actually wrong; we should be using the knowledge about
whether we have called add_window / remove_window. We'll introduce
this with a new boolean next time.
2014-03-28 13:51:34 -04:00
e10fd19d24 events: Make sure to check the event window of the MapNotify
This was lost in a rebase when killing off zaphod mode.
2014-03-28 13:46:46 -04:00
f4f529385a Fix the build with -Werror=maybe-uninitialized
gcc can't really know that the condition won't change between
the first if and the second, so help it out by initializing
the variable up top.
2014-03-27 14:58:20 -04:00
3f70bdd331 display: Revert API break for get_tab_list
gnome-shell apparently uses this, and we shouldn't break it.
2014-03-27 12:48:05 -04:00
6eeaf09ab7 compositor: Don't call process_damage if the window is gone
We might get a damage event for an already unmanaged window calling
process_damage is pointless and causes a crash so simply skip that case.

https://bugzilla.gnome.org/show_bug.cgi?id=727115
2014-03-27 14:06:27 +01:00
cd905a34fb compositor: Kill off MetaCompScreen
Compositors haven't been able to manage more than one screen for
quite a while. Merge MetaCompScreen into MetaCompositor, and update
the API to match.

We still keep MetaScreen in the public compositor API for compatibility
purposes.
2014-03-26 12:04:48 -04:00
47aa583625 display: Kill off grab_screen
Just like active_screen, the screen can always be inferred
from the MetaDisplay, so there's no point in keeping it around.
2014-03-26 12:04:48 -04:00
d7519f4ebc Remove any possibility for zaphod mode
We previously separated out MetaDisplay and MetaScreen. mutter
would only manage one screen, but we still kept a list of screens
for simplicity.

With Wayland support, we no longer care about the ability to
manage more than one screen at a time. Remove this by killing
the list of screens, in favor of having just one MetaScreen
in MetaDisplay.

We also kill off active_screen at the same time, since it's
not necessary anymore.

A future cleanup should merge MetaDisplay and MetaScreen. To avoid
breaking API, we should probably keep MetaScreen around as a dummy
type.
2014-03-26 12:04:48 -04:00
97ea4e8717 xwayland: Remove some stray logs
These really aren't too helpful.
2014-03-26 12:04:14 -04:00
208296a619 wayland: Shut up about Setenv if we're past initialization
I'm a bit tired of hearing about this when I launch mutter-wayland
nested. Ideally, this would be part of display server integration,
not GNOME integration, so we could simply not make the call when
nested, but oh well.
2014-03-26 12:02:08 -04:00
cc0488f1e2 surface-actor: Implement is_argb32 generically for both X11 and Wayland
cogl_texture_get_components can be used on both X11 and Wayland
backends. Technically, the detection is different: we actually
check the actual RENDER format in the old code, while Cogl simply
assumes that any pixmap with a depth >= 32 is ARGB32. Since Cogl
already seems to be working with its internal checks, it makes
more sense to  use Cogl's check rather than keeping our own.
2014-03-25 17:04:39 -04:00
e30ed6892c surface-actor: Prevent a dumb crash
is_argb32 can be called at any time, including times when we don't
have a texture. In that case, just assume we're ARGB32. The value
really shouldn't be important though.
2014-03-25 17:04:37 -04:00
d699b2409a xwayland: Shut up conditionally 2014-03-25 12:54:13 -04:00
ef65848d11 window-wayland: Implement kill 2014-03-25 12:05:21 -04:00
272676b896 surface-actor-wayland: Make sure to clean up on dispose
We need to remove our destroy handler if the surface is destroyed
before the buffer is, which is the case when we have no destroy
effect.
2014-03-25 12:00:38 -04:00
44580ddb80 wayland-surface: Unref the buffer after removing the destroy listener 2014-03-25 12:00:38 -04:00
456e3e2429 xwayland: Punt stdout / stderr to /dev/null
This should really go to the journal, but I'm tired of seeing Xorg
log a bunch of garbage that I don't care about when debugging mutter.
2014-03-25 12:00:38 -04:00
91 changed files with 4440 additions and 3993 deletions

3
.gitignore vendored
View File

@ -75,7 +75,7 @@ src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-xrandr.[ch]
src/meta-dbus-display-config.[ch]
src/meta-dbus-idle-monitor.[ch]
src/mutter-plugins.pc
src/gtk-shell-protocol.c
@ -108,3 +108,4 @@ ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
.dirstamp

View File

@ -16,7 +16,7 @@ AC_INIT([mutter], [mutter_version],
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE([enable])
@ -480,7 +480,6 @@ mutter-wayland-$VERSION
Session management: ${found_sm}
Shape extension: ${found_shape}
Xsync: ${found_xsync}
Xcursor: ${have_xcursor}
"

View File

@ -13,6 +13,7 @@ INCLUDES= \
$(MUTTER_CFLAGS) \
-I$(top_builddir) \
-I$(srcdir) \
-I$(srcdir)/backends \
-I$(srcdir)/core \
-I$(srcdir)/ui \
-I$(srcdir)/compositor \
@ -34,7 +35,7 @@ INCLUDES= \
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_xrandr_built_sources) \
$(dbus_display_config_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
gtk-shell-protocol.c \
@ -50,6 +51,40 @@ wayland_protocols = \
wayland/protocol/xserver.xml
libmutter_wayland_la_SOURCES = \
backends/meta-backend.c \
backends/meta-backend.h \
backends/meta-cursor.c \
backends/meta-cursor.h \
backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \
backends/meta-idle-monitor.c \
backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \
backends/meta-idle-monitor-dbus.h \
backends/meta-monitor-config.c \
backends/meta-monitor-config.h \
backends/meta-monitor-manager.c \
backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \
backends/edid.h \
backends/native/meta-cursor-tracker-native.c \
backends/native/meta-cursor-tracker-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-weston-launch.c \
backends/native/meta-weston-launch.h \
backends/x11/meta-cursor-tracker-x11.c \
backends/x11/meta-cursor-tracker-x11.h \
backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
backends/x11/meta-xrandr-shared.h \
core/above-tab-keycode.c \
core/barrier.c \
meta/barrier.h \
@ -114,8 +149,6 @@ libmutter_wayland_la_SOURCES = \
meta/display.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/edid-parse.c \
core/edid.h \
core/events.c \
core/events.h \
core/errors.c \
@ -127,17 +160,6 @@ libmutter_wayland_la_SOURCES = \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
core/meta-cursor-tracker.c \
core/meta-cursor-tracker-private.h \
core/meta-idle-monitor.c \
core/meta-idle-monitor-private.h \
core/meta-xrandr-shared.h \
core/monitor.c \
core/monitor-config.c \
core/monitor-kms.c \
core/monitor-private.h \
core/monitor-xrandr.c \
core/mutter-Xatomtype.h \
core/place.c \
core/place.h \
core/prefs.c \
@ -192,6 +214,7 @@ libmutter_wayland_la_SOURCES = \
x11/window-x11-private.h \
x11/xprops.c \
x11/xprops.h \
x11/mutter-Xatomtype.h \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
@ -211,8 +234,6 @@ libmutter_wayland_la_SOURCES = \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \
wayland/meta-weston-launch.c \
wayland/meta-weston-launch.h \
wayland/window-wayland.c \
wayland/window-wayland.h
@ -271,7 +292,9 @@ 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_SOURCES = \
backends/native/weston-launch.c \
backends/native/weston-launch.h
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
@ -373,7 +396,8 @@ EXTRA_DIST=$(desktopfiles_files) \
libmutter-wayland.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \
xrandr.xml idle-monitor.xml
org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
@ -398,23 +422,22 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
cp xgen-tetc mutter-enum-types.c && \
rm -f xgen-tetc
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
dbus_display_config_built_sources = meta-dbus-display-config.c meta-dbus-display-config.h
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
$(dbus_display_config_built_sources) : Makefile.am org.gnome.Mutter.DisplayConfig.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-xrandr \
$(srcdir)/xrandr.xml
--generate-c-code meta-dbus-display-config \
$(srcdir)/org.gnome.Mutter.DisplayConfig.xml
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
$(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-idle-monitor \
--c-generate-object-manager \
$(srcdir)/idle-monitor.xml
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@

157
src/backends/meta-backend.c Normal file
View File

@ -0,0 +1,157 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-backend.h"
#include <meta/main.h>
#include <gdk/gdkx.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include "backends/native/meta-weston-launch.h"
#include <meta/util.h>
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
* the X fd, but we do have to deal with dispatching events that accumulate
* in the clutter queue. This happens, for example, when clutter generate
* enter/leave events on mouse motion - several events are queued in the
* clutter queue but only one dispatched. It could also happen because of
* explicit calls to clutter_event_put(). We add a very simple custom
* event loop source which is simply responsible for pulling events off
* of the queue and dispatching them before we block for new events.
*/
static gboolean
event_prepare (GSource *source,
gint *timeout_)
{
*timeout_ = -1;
return clutter_events_pending ();
}
static gboolean
event_check (GSource *source)
{
return clutter_events_pending ();
}
static gboolean
event_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterEvent *event = clutter_event_get ();
if (event)
{
clutter_do_event (event);
clutter_event_free (event);
}
return TRUE;
}
static GSourceFuncs event_funcs = {
event_prepare,
event_check,
event_dispatch
};
static MetaLauncher *launcher;
void
meta_clutter_init (void)
{
GSource *source;
/* When running as an X11 compositor, we install our own event filter and
* pass events to Clutter explicitly, so we need to prevent Clutter from
* handling our events.
*
* However, when running as a Wayland compostior under X11 nested, Clutter
* Clutter needs to see events related to its own window. We need to
* eventually replace this with a proper frontend / backend split: Clutter
* under nested is connecting to the "host X server" to get its events it
* needs to put up a window, and GTK+ is connecting to the "inner X server".
* The two would the same in the X11 compositor case, but not when running
* XWayland as a Wayland compositor.
*/
if (!meta_is_wayland_compositor ())
{
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
}
/* If we're running on bare metal, we're a display server,
* so start talking to weston-launch. */
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
launcher = meta_launcher_new ();
#endif
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n");
source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);
}
gboolean
meta_activate_vt (int vt, GError **error)
{
if (launcher)
return meta_launcher_activate_vt (launcher, vt, error);
else
{
g_debug ("Ignoring VT switch keybinding, not running as display server");
return TRUE;
}
}
/**
* 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)
{
GError *error = NULL;
if (!meta_launcher_activate_vt (launcher, -1, &error))
{
g_warning ("Could not activate session: %s\n", error->message);
g_error_free (error);
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,34 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_BACKEND_H
#define META_BACKEND_H
#include <glib-object.h>
void meta_clutter_init (void);
gboolean meta_activate_vt (int vt, GError **error);
#endif /* META_BACKEND_H */

View File

@ -0,0 +1,77 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_PRIVATE_H
#define META_CURSOR_PRIVATE_H
#include "meta-cursor.h"
#include <cogl/cogl.h>
#include <gbm.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <wayland-server.h>
typedef struct {
CoglTexture2D *texture;
struct gbm_bo *bo;
int hot_x, hot_y;
} MetaCursorImage;
struct _MetaCursorReference {
int ref_count;
MetaCursorImage image;
};
CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
void meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t gbm_format);
void meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
struct wl_resource *buffer,
int width,
int height);
MetaCursorReference *meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image);
MetaCursorReference *meta_cursor_reference_from_xcursor_image (XcursorImage *xc_image);
MetaCursorReference *meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif /* META_CURSOR_PRIVATE_H */

View File

@ -0,0 +1,116 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_PRIVATE_H
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include "meta-cursor.h"
struct _MetaCursorTracker {
GObject parent_instance;
gboolean is_showing;
/* 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;
/* This is the cursor that would be displayed if we hadn't been
* asked to hide it. i.e. it's the same as displayed_cursor unless
* is_showing is false.
*/
MetaCursorReference *current_cursor;
MetaCursorReference *grab_cursor;
/* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything.
* So, we can't simply store a NULL in window_cursor to
* determine an unset window cursor; we need an extra boolean.
*/
gboolean has_window_cursor;
MetaCursorReference *window_cursor;
MetaCursorReference *root_cursor;
MetaCursorReference *theme_cursors[META_CURSOR_LAST];
};
struct _MetaCursorTrackerClass {
GObjectClass parent_class;
void (*get_pointer) (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods);
void (*sync_cursor) (MetaCursorTracker *tracker);
void (*ensure_cursor) (MetaCursorTracker *tracker);
void (*load_cursor_pixels) (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t format);
void (*load_cursor_buffer) (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
struct wl_resource *buffer);
};
void _meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor);
void _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
MetaCursor cursor);
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif

View File

@ -0,0 +1,351 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
/**
* SECTION:cursor-tracker
* @title: MetaCursorTracker
* @short_description: Mutter cursor tracking helper. Originally only
* tracking the cursor image, now more of a "core
* pointer abstraction"
*/
#include <config.h>
#include <string.h>
#include <meta/main.h>
#include <meta/util.h>
#include <meta/errors.h>
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
#include "backends/x11/meta-cursor-tracker-x11.h"
#include "screen-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum {
CURSOR_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
detecting if the system mouse cursor is showing or not.
On wayland we start with the cursor showing
*/
self->is_showing = TRUE;
}
static void
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->root_cursor)
meta_cursor_reference_unref (self->root_cursor);
for (i = 0; i < META_CURSOR_LAST; i++)
if (self->theme_cursors[i])
meta_cursor_reference_unref (self->theme_cursors[i]);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
}
static void
default_do_nothing (MetaCursorTracker *tracker)
{
}
static void
default_load_cursor_pixels (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t format)
{
}
static void
default_load_cursor_buffer (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
struct wl_resource *buffer)
{
}
static void
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_cursor_tracker_finalize;
klass->sync_cursor = default_do_nothing;
klass->ensure_cursor = default_do_nothing;
klass->load_cursor_pixels = default_load_cursor_pixels;
klass->load_cursor_buffer = default_load_cursor_buffer;
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
/**
* meta_cursor_tracker_get_for_screen:
* @screen: the #MetaScreen
*
* Retrieves the cursor tracker object for @screen.
*
* Returns: (transfer none):
*/
MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
MetaCursorTracker *self;
if (screen->cursor_tracker)
return screen->cursor_tracker;
if (meta_is_wayland_compositor ())
self = g_object_new (META_TYPE_CURSOR_TRACKER_NATIVE, NULL);
else
self = g_object_new (META_TYPE_CURSOR_TRACKER_X11, NULL);
screen->cursor_tracker = self;
return self;
}
/**
* meta_cursor_tracker_get_sprite:
*
* Returns: (transfer none):
*/
CoglTexture *
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
if (tracker->current_cursor)
return meta_cursor_reference_get_cogl_texture (tracker->current_cursor, NULL, NULL);
else
return NULL;
}
/**
* meta_cursor_tracker_get_hot:
* @tracker:
* @x: (out):
* @y: (out):
*
*/
void
meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
int *x,
int *y)
{
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
if (tracker->current_cursor)
meta_cursor_reference_get_cogl_texture (tracker->current_cursor, x, y);
else
{
if (x)
*x = 0;
if (y)
*y = 0;
}
}
void
_meta_cursor_tracker_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;
_meta_cursor_tracker_sync_cursor (tracker);
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
_meta_cursor_tracker_set_window_cursor (tracker, TRUE, cursor);
}
void
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
{
_meta_cursor_tracker_set_window_cursor (tracker, FALSE, NULL);
}
void
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
_meta_cursor_tracker_sync_cursor (tracker);
}
void
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->root_cursor = meta_cursor_reference_ref (cursor);
_meta_cursor_tracker_sync_cursor (tracker);
}
static MetaCursorReference *
get_current_cursor (MetaCursorTracker *tracker)
{
if (tracker->grab_cursor)
return tracker->grab_cursor;
if (tracker->has_window_cursor)
return tracker->window_cursor;
return tracker->root_cursor;
}
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
if (!tracker->is_showing)
return NULL;
return get_current_cursor (tracker);
}
void
_meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *current_cursor = get_current_cursor (tracker);
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor != displayed_cursor)
{
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
META_CURSOR_TRACKER_GET_CLASS (tracker)->sync_cursor (tracker);
}
if (tracker->current_cursor != current_cursor)
{
g_clear_pointer (&tracker->current_cursor, meta_cursor_reference_unref);
if (current_cursor)
tracker->current_cursor = meta_cursor_reference_ref (current_cursor);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
}
}
void
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
META_CURSOR_TRACKER_GET_CLASS (tracker)->get_pointer (tracker, x, y, mods);
}
void
meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
gboolean visible)
{
if (visible == tracker->is_showing)
return;
tracker->is_showing = visible;
_meta_cursor_tracker_sync_cursor (tracker);
}
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
MetaCursor meta_cursor)
{
MetaCursorReference *cursor;
XcursorImage *xc_image;
if (tracker->theme_cursors[meta_cursor])
return meta_cursor_reference_ref (tracker->theme_cursors[meta_cursor]);
xc_image = meta_display_load_x_cursor (meta_get_display (), meta_cursor);
if (!xc_image)
return NULL;
cursor = meta_cursor_reference_from_xcursor_image (xc_image);
META_CURSOR_TRACKER_GET_CLASS (tracker)->load_cursor_pixels (tracker,
cursor,
(uint8_t *) xc_image->pixels,
xc_image->width,
xc_image->height,
xc_image->width * 4,
GBM_FORMAT_ARGB8888);
XcursorImageDestroy (xc_image);
tracker->theme_cursors[meta_cursor] = cursor;
return meta_cursor_reference_ref (cursor);
}
MetaCursorReference *
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *cursor;
cursor = meta_cursor_reference_from_buffer (buffer, hot_x, hot_y);
META_CURSOR_TRACKER_GET_CLASS (tracker)->load_cursor_buffer (tracker,
cursor,
buffer);
return cursor;
}

400
src/backends/meta-cursor.c Normal file
View File

@ -0,0 +1,400 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#include "config.h"
#include "meta-cursor-private.h"
#include <meta/errors.h>
#include "display-private.h"
#include "screen-private.h"
#include "meta-cursor-tracker-private.h"
#include <string.h>
#include <cogl/cogl-wayland-server.h>
static MetaCursorReference *
meta_cursor_reference_new (void)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
return self;
}
MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
{
g_assert (self->ref_count > 0);
self->ref_count++;
return self;
}
static void
meta_cursor_image_free (MetaCursorImage *image)
{
cogl_object_unref (image->texture);
if (image->bo)
gbm_bo_destroy (image->bo);
}
static void
meta_cursor_reference_free (MetaCursorReference *self)
{
meta_cursor_image_free (&self->image);
g_slice_free (MetaCursorReference, self);
}
void
meta_cursor_reference_unref (MetaCursorReference *self)
{
self->ref_count--;
if (self->ref_count == 0)
meta_cursor_reference_free (self);
}
static void
translate_meta_cursor (MetaCursor cursor,
guint *glyph_out,
const char **name_out)
{
guint glyph = XC_num_glyphs;
const char *name = NULL;
switch (cursor)
{
case META_CURSOR_DEFAULT:
glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE:
glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE:
glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE:
glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE:
glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE:
glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE:
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_left_corner;
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
glyph = XC_fleur;
break;
case META_CURSOR_BUSY:
glyph = XC_watch;
break;
case META_CURSOR_DND_IN_DRAG:
name = "dnd-none";
break;
case META_CURSOR_DND_MOVE:
name = "dnd-move";
break;
case META_CURSOR_DND_COPY:
name = "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET:
name = "dnd-none";
break;
case META_CURSOR_POINTING_HAND:
glyph = XC_hand2;
break;
case META_CURSOR_CROSSHAIR:
glyph = XC_crosshair;
break;
case META_CURSOR_IBEAM:
glyph = XC_xterm;
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
}
*glyph_out = glyph;
*name_out = name;
}
static Cursor
load_cursor_on_server (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph;
const char *name;
translate_meta_cursor (cursor, &glyph, &name);
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
}
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return load_cursor_on_server (display, cursor);
}
static XcursorImage *
load_cursor_on_client (MetaDisplay *display,
MetaCursor cursor)
{
XcursorImage *image;
guint glyph;
const char *name;
const char *theme = XcursorGetTheme (display->xdisplay);
int size = XcursorGetDefaultSize (display->xdisplay);
translate_meta_cursor (cursor, &glyph, &name);
if (name != NULL)
image = XcursorLibraryLoadImage (name, theme, size);
else
image = XcursorShapeLoadImage (glyph, theme, size);
return image;
}
XcursorImage *
meta_display_load_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return load_cursor_on_client (display, cursor);
}
void
meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t gbm_format)
{
if (width > 64 || height > 64)
{
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
return;
}
if (gbm_device_is_format_supported (gbm, gbm_format,
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{
uint8_t buf[4 * 64 * 64];
int i;
cursor->image.bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
gbm_bo_write (cursor->image.bo, buf, 64 * 64 * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
void
meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
struct gbm_device *gbm,
struct wl_resource *buffer,
int width,
int height)
{
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
cursor->image.bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!cursor->image.bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
MetaCursorReference *
meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image)
{
MetaCursorReference *cursor;
CoglTexture2D *sprite;
CoglContext *ctx;
guint8 *cursor_data;
gboolean free_cursor_data;
cursor = meta_cursor_reference_new ();
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
* quantities as arrays of long; we need to convert on 64 bit */
if (sizeof(long) == 4)
{
cursor_data = (guint8 *)cursor_image->pixels;
free_cursor_data = FALSE;
}
else
{
int i, j;
guint32 *cursor_words;
gulong *p;
guint32 *q;
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
cursor_data = (guint8 *)cursor_words;
p = cursor_image->pixels;
q = cursor_words;
for (j = 0; j < cursor_image->height; j++)
for (i = 0; i < cursor_image->width; i++)
*(q++) = *(p++);
free_cursor_data = TRUE;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
sprite = cogl_texture_2d_new_from_data (ctx,
cursor_image->width,
cursor_image->height,
CLUTTER_CAIRO_FORMAT_ARGB32,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
if (free_cursor_data)
g_free (cursor_data);
cursor->image.texture = sprite;
cursor->image.hot_x = cursor_image->xhot;
cursor->image.hot_y = cursor_image->yhot;
return cursor;
}
MetaCursorReference *
meta_cursor_reference_from_xcursor_image (XcursorImage *xc_image)
{
MetaCursorReference *cursor;
int width, height, rowstride;
CoglPixelFormat cogl_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
cursor = meta_cursor_reference_new ();
width = xc_image->width;
height = xc_image->height;
rowstride = width * 4;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif
cursor->image.hot_x = xc_image->xhot;
cursor->image.hot_y = xc_image->yhot;
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
cursor->image.texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
NULL);
return cursor;
}
MetaCursorReference *
meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *cursor;
ClutterBackend *backend;
CoglContext *cogl_context;
cursor = meta_cursor_reference_new ();
cursor->image.hot_x = hot_x;
cursor->image.hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cursor->image.texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
return cursor;
}
CoglTexture *
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return COGL_TEXTURE (cursor->image.texture);
}
struct gbm_bo *
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return cursor->image.bo;
}

View File

@ -0,0 +1,30 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_H
#define META_CURSOR_H
typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor);
#endif /* META_CURSOR_H */

View File

@ -16,7 +16,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
/* This file is shared between mutter (src/core/meta-display-config-shared.h)
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
The canonical place for all changes is mutter.
@ -24,8 +24,8 @@
There should be no includes in this file.
*/
#ifndef META_XRANDR_SHARED_H
#define META_XRANDR_SHARED_H
#ifndef META_DISPLAY_CONFIG_SHARED_H
#define META_DISPLAY_CONFIG_SHARED_H
typedef enum {
META_POWER_SAVE_UNSUPPORTED = -1,
@ -35,4 +35,4 @@ typedef enum {
META_POWER_SAVE_OFF,
} MetaPowerSave;
#endif
#endif /* META_DISPLAY_CONFIG_SHARED_H */

View File

@ -0,0 +1,286 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-dbus.h"
#include <meta/meta-idle-monitor.h>
#include "meta-dbus-idle-monitor.h"
#include <clutter/clutter.h>
#include <meta/util.h>
#include <meta/main.h> /* for meta_get_replace_current_wm () */
static gboolean
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
guint64 idletime;
idletime = meta_idle_monitor_get_idletime (monitor);
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
return TRUE;
}
typedef struct {
MetaDBusIdleMonitor *dbus_monitor;
MetaIdleMonitor *monitor;
char *dbus_name;
guint watch_id;
guint name_watcher_id;
} DBusWatch;
static void
destroy_dbus_watch (gpointer data)
{
DBusWatch *watch = data;
g_object_unref (watch->dbus_monitor);
g_object_unref (watch->monitor);
g_free (watch->dbus_name);
g_bus_unwatch_name (watch->name_watcher_id);
g_slice_free (DBusWatch, watch);
}
static void
dbus_idle_callback (MetaIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
DBusWatch *watch = user_data;
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
watch->dbus_name,
g_dbus_interface_skeleton_get_object_path (skeleton),
"org.gnome.Mutter.IdleMonitor",
"WatchFired",
g_variant_new ("(u)", watch_id),
NULL);
}
static void
name_vanished_callback (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
DBusWatch *watch = user_data;
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
}
static DBusWatch *
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = g_slice_new (DBusWatch);
watch->dbus_monitor = g_object_ref (skeleton);
watch->monitor = g_object_ref (monitor);
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
watch->dbus_name,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL, /* appeared */
name_vanished_callback,
watch, NULL);
return watch;
}
static gboolean
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint64 interval,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
dbus_idle_callback, watch, destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
dbus_idle_callback, watch,
destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint id,
MetaIdleMonitor *monitor)
{
meta_idle_monitor_remove_watch (monitor, id);
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
return TRUE;
}
static void
create_monitor_skeleton (GDBusObjectManagerServer *manager,
MetaIdleMonitor *monitor,
const char *path)
{
MetaDBusIdleMonitor *skeleton;
MetaDBusObjectSkeleton *object;
skeleton = meta_dbus_idle_monitor_skeleton_new ();
g_signal_connect_object (skeleton, "handle-add-idle-watch",
G_CALLBACK (handle_add_idle_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-remove-watch",
G_CALLBACK (handle_remove_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-get-idletime",
G_CALLBACK (handle_get_idletime), monitor, 0);
object = meta_dbus_object_skeleton_new (path);
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
MetaIdleMonitor *monitor;
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
monitor = meta_idle_monitor_get_for_device (device_id);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
create_monitor_skeleton (manager, monitor, path);
g_free (path);
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
g_dbus_object_manager_server_unexport (manager, path);
g_free (path);
}
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
GDBusObjectManagerServer *manager;
ClutterDeviceManager *device_manager;
MetaIdleMonitor *monitor;
GSList *devices, *iter;
char *path;
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
/* We never clear the core monitor, as that's supposed to cumulate idle times from
all devices */
monitor = meta_idle_monitor_get_core ();
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
create_monitor_skeleton (manager, monitor, path);
g_free (path);
device_manager = clutter_device_manager_get_default ();
devices = clutter_device_manager_list_devices (device_manager);
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",
G_CALLBACK (on_device_removed), manager, 0);
g_dbus_object_manager_server_set_connection (manager, connection);
}
static void
on_name_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Acquired name %s\n", name);
}
static void
on_name_lost (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Lost or failed to acquire name %s\n", name);
}
void
meta_idle_monitor_init_dbus (void)
{
static int dbus_name_id;
if (dbus_name_id > 0)
return;
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.gnome.Mutter.IdleMonitor",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
(meta_get_replace_current_wm () ?
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL, NULL);
}

View File

@ -1,8 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright 2013 Red Hat, Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,7 +12,7 @@
* 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/>.
*
@ -20,10 +20,9 @@
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include <meta/meta-idle-monitor.h>
void meta_idle_monitor_handle_xevent_all (XEvent *xevent);
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
#ifndef META_IDLE_MONITOR_DBUS_H
#define META_IDLE_MONITOR_DBUS_H
void meta_idle_monitor_init_dbus (void);
#endif

View File

@ -0,0 +1,65 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_PRIVATE_H
#define META_IDLE_MONITOR_PRIVATE_H
#include <meta/meta-idle-monitor.h>
#include "display-private.h"
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
typedef struct
{
MetaIdleMonitor *monitor;
guint id;
MetaIdleMonitorWatchFunc callback;
gpointer user_data;
GDestroyNotify notify;
guint64 timeout_msec;
int idle_source_id;
} MetaIdleMonitorWatch;
struct _MetaIdleMonitor
{
GObject parent_instance;
GHashTable *watches;
int device_id;
};
struct _MetaIdleMonitorClass
{
GObjectClass parent_class;
gint64 (*get_idletime) (MetaIdleMonitor *monitor);
MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify);
};
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
#endif /* META_IDLE_MONITOR_PRIVATE_H */

View File

@ -0,0 +1,367 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
/**
* SECTION:idle-monitor
* @title: MetaIdleMonitor
* @short_description: Mutter idle counter (similar to X's IDLETIME)
*/
#include "config.h"
#include <string.h>
#include <clutter/clutter.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "backends/x11/meta-idle-monitor-xsync.h"
#include "backends/native/meta-idle-monitor-native.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
enum
{
PROP_0,
PROP_DEVICE_ID,
PROP_LAST,
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
static MetaIdleMonitor *device_monitors[256];
static int device_id_max;
void
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
guint id;
gboolean is_user_active_watch;
monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
id = watch->id;
is_user_active_watch = (watch->timeout_msec == 0);
if (watch->callback)
watch->callback (monitor, id, watch->user_data);
if (is_user_active_watch)
meta_idle_monitor_remove_watch (monitor, id);
g_object_unref (monitor);
}
static void
meta_idle_monitor_dispose (GObject *object)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
}
static void
meta_idle_monitor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
g_value_set_int (value, monitor->device_id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
monitor->device_id = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_idle_monitor_dispose;
object_class->get_property = meta_idle_monitor_get_property;
object_class->set_property = meta_idle_monitor_set_property;
/**
* MetaIdleMonitor:device_id:
*
* The device to listen to idletime on.
*/
obj_props[PROP_DEVICE_ID] =
g_param_spec_int ("device-id",
"Device ID",
"The device to listen to idletime on",
0, 255, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
}
static void
meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
}
static GType
get_idle_monitor_type (void)
{
if (meta_is_wayland_compositor ())
return META_TYPE_IDLE_MONITOR_NATIVE;
else
return META_TYPE_IDLE_MONITOR_XSYNC;
}
static void
ensure_device_monitor (int device_id)
{
if (device_monitors[device_id])
return;
device_monitors[device_id] = g_object_new (get_idle_monitor_type (),
"device-id", device_id,
NULL);
device_id_max = MAX (device_id_max, device_id);
}
/* FIXME -- destroy device monitors at some point */
G_GNUC_UNUSED static void
destroy_device_monitor (int device_id)
{
g_clear_object (&device_monitors[device_id]);
if (device_id == device_id_max)
device_id_max--;
}
/**
* meta_idle_monitor_get_core:
*
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
* idletime for all devices. To track device-specific idletime,
* use meta_idle_monitor_get_for_device().
*/
MetaIdleMonitor *
meta_idle_monitor_get_core (void)
{
ensure_device_monitor (0);
return device_monitors[0];
}
/**
* meta_idle_monitor_get_for_device:
* @device_id: the device to get the idle time for.
*
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
* device-specific idletime for @device. To track server-global idletime
* for all devices, use meta_idle_monitor_get_core().
*/
MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id)
{
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
ensure_device_monitor (device_id);
return device_monitors[device_id];
}
static MetaIdleMonitorWatch *
make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
timeout_msec,
callback,
user_data,
notify);
g_hash_table_insert (monitor->watches,
GUINT_TO_POINTER (watch->id),
watch);
return watch;
}
/**
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (allow-none): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Adds a watch for a specific idle time. The callback will be called
* when the user has accumulated @interval_msec milliseconds of idle time.
* This function will return an ID that can either be passed to
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
* watches apart if you have more than one.
*
* Also note that this function will only care about positive transitions
* (user's idle time exceeding a certain time). If you want to know about
* when the user has become active, use
* meta_idle_monitor_add_user_active_watch().
*/
guint
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
guint64 interval_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
g_return_val_if_fail (interval_msec > 0, 0);
watch = make_watch (monitor,
interval_msec,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (allow-none): The callback to call when the user is
* active again.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Add a one-time watch to know when the user is active again.
* Note that this watch is one-time and will de-activate after the
* function is called, for efficiency purposes. It's most convenient
* to call this when an idle watch, as added by
* meta_idle_monitor_add_idle_watch(), has triggered.
*/
guint
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
watch = make_watch (monitor,
0,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_remove_watch:
* @monitor: A #MetaIdleMonitor
* @id: A watch ID
*
* Removes an idle time watcher, previously added by
* meta_idle_monitor_add_idle_watch() or
* meta_idle_monitor_add_user_active_watch().
*/
void
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
guint id)
{
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);
}
/**
* meta_idle_monitor_get_idletime:
* @monitor: A #MetaIdleMonitor
*
* Returns: The current idle time, in milliseconds, or -1 for not supported
*/
gint64
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
}
void
meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent)
{
int i;
if (meta_is_wayland_compositor ())
return;
for (i = 0; i <= device_id_max; i++)
if (device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}

View File

@ -34,13 +34,14 @@
#include "config.h"
#include "meta-monitor-config.h"
#include <string.h>
#include <clutter/clutter.h>
#include <libupower-glib/upower.h>
#include <meta/main.h>
#include <meta/errors.h>
#include "monitor-private.h"
/* These structures represent the intended/persistent configuration,
as stored in the monitors.xml file.

View File

@ -0,0 +1,55 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_CONFIG_H
#define META_MONITOR_CONFIG_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_default (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_update_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
MetaMonitorManager *manager);
#endif /* META_MONITOR_CONFIG_H */

View File

@ -0,0 +1,227 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001, 2002 Havoc Pennington
* Copyright (C) 2002, 2003 Red Hat Inc.
* Some ICCCM manager selection code derived from fvwm2,
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "meta-monitor-manager-dummy.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
{
MetaMonitorManager parent_instance;
};
struct _MetaMonitorManagerDummyClass
{
MetaMonitorManagerClass parent_class;
};
G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER);
static void
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
{
manager->max_screen_width = 65535;
manager->max_screen_height = 65535;
manager->screen_width = 1024;
manager->screen_height = 768;
manager->modes = g_new0 (MetaMonitorMode, 1);
manager->n_modes = 1;
manager->modes[0].mode_id = 0;
manager->modes[0].width = 1024;
manager->modes[0].height = 768;
manager->modes[0].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 1);
manager->n_crtcs = 1;
manager->crtcs[0].crtc_id = 1;
manager->crtcs[0].rect.x = 0;
manager->crtcs[0].rect.y = 0;
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 1);
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
manager->outputs[0].width_mm = 222;
manager->outputs[0].height_mm = 125;
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[0].preferred_mode = &manager->modes[0];
manager->outputs[0].n_modes = 1;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
manager->outputs[0].modes[0] = &manager->modes[0];
manager->outputs[0].n_possible_crtcs = 1;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[0].backlight = -1;
manager->outputs[0].backlight_min = 0;
manager->outputs[0].backlight_max = 0;
}
static void
meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
unsigned i;
int screen_width = 0, screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
crtc->is_dirty = TRUE;
if (crtc_info->mode == NULL)
{
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
else
{
MetaMonitorMode *mode;
MetaOutput *output;
int i, n_outputs;
int width, height;
mode = crtc_info->mode;
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = mode->height;
height = mode->width;
}
else
{
width = mode->width;
height = mode->height;
}
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
crtc->rect.height = height;
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
n_outputs = crtc_info->outputs->len;
for (i = 0; i < n_outputs; i++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
output->is_dirty = TRUE;
output->crtc = crtc;
}
}
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
}
/* Disable CRTCs not mentioned in the list */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
crtc->logical_monitor = NULL;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
/* Disable outputs not mentioned in the list */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
output->crtc = NULL;
output->is_primary = FALSE;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
meta_monitor_manager_rebuild_derived (manager);
}
static void
meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
manager_class->read_current = meta_monitor_manager_dummy_read_current;
manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config;
}
static void
meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager)
{
}

View File

@ -0,0 +1,40 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_MANAGER_DUMMY_H
#define META_MONITOR_MANAGER_DUMMY_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ())
#define META_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy))
#define META_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass))
#define META_IS_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_DUMMY))
#define META_IS_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_DUMMY))
#define META_MONITOR_MANAGER_DUMMY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass))
typedef struct _MetaMonitorManagerDummyClass MetaMonitorManagerDummyClass;
typedef struct _MetaMonitorManagerDummy MetaMonitorManagerDummy;
GType meta_monitor_manager_dummy_get_type (void);
#endif /* META_MONITOR_MANAGER_DUMMY_H */

View File

@ -25,6 +25,8 @@
#include "config.h"
#include "meta-monitor-manager.h"
#include <string.h>
#include <math.h>
#include <stdlib.h>
@ -33,11 +35,10 @@
#include <meta/main.h>
#include "util-private.h"
#include <meta/errors.h>
#include "monitor-private.h"
#include "meta-dbus-xrandr.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
#include "meta-monitor-config.h"
#include "backends/native/meta-monitor-manager-kms.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-monitor-manager-dummy.h"
enum {
CONFIRM_DISPLAY_CHANGE,
@ -54,196 +55,11 @@ static int signals[SIGNALS_LAST];
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYPE_DISPLAY_CONFIG_SKELETON,
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DISPLAY_CONFIG, meta_monitor_manager_display_config_init));
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYPE_DISPLAY_CONFIG_SKELETON,
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DISPLAY_CONFIG, meta_monitor_manager_display_config_init));
static void initialize_dbus_interface (MetaMonitorManager *manager);
static void
read_current_dummy (MetaMonitorManager *manager)
{
manager->max_screen_width = 65535;
manager->max_screen_height = 65535;
manager->screen_width = 1024;
manager->screen_height = 768;
manager->modes = g_new0 (MetaMonitorMode, 1);
manager->n_modes = 1;
manager->modes[0].mode_id = 0;
manager->modes[0].width = 1024;
manager->modes[0].height = 768;
manager->modes[0].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 1);
manager->n_crtcs = 1;
manager->crtcs[0].crtc_id = 1;
manager->crtcs[0].rect.x = 0;
manager->crtcs[0].rect.y = 0;
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 1);
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
manager->outputs[0].width_mm = 222;
manager->outputs[0].height_mm = 125;
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[0].preferred_mode = &manager->modes[0];
manager->outputs[0].n_modes = 1;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
manager->outputs[0].modes[0] = &manager->modes[0];
manager->outputs[0].n_possible_crtcs = 1;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[0].backlight = -1;
manager->outputs[0].backlight_min = 0;
manager->outputs[0].backlight_max = 0;
}
static void
apply_config_dummy (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
unsigned i;
int screen_width = 0, screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
crtc->is_dirty = TRUE;
if (crtc_info->mode == NULL)
{
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
else
{
MetaMonitorMode *mode;
MetaOutput *output;
int i, n_outputs;
int width, height;
mode = crtc_info->mode;
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = mode->height;
height = mode->width;
}
else
{
width = mode->width;
height = mode->height;
}
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
crtc->rect.height = height;
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
n_outputs = crtc_info->outputs->len;
for (i = 0; i < n_outputs; i++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
output->is_dirty = TRUE;
output->crtc = crtc;
}
}
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
}
/* Disable CRTCs not mentioned in the list */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
crtc->logical_monitor = NULL;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
/* Disable outputs not mentioned in the list */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
output->crtc = NULL;
output->is_primary = FALSE;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
meta_monitor_manager_rebuild_derived (manager);
}
static GBytes *
read_edid_dummy (MetaMonitorManager *manager,
MetaOutput *output)
{
return NULL;
}
static char *
get_edid_file_dummy (MetaMonitorManager *manager,
MetaOutput *output)
{
return NULL;
}
static void
meta_monitor_manager_init (MetaMonitorManager *manager)
{
@ -367,7 +183,7 @@ get_default_backend (void)
* we're a nested configuration, so return the dummy
* monitor setup. */
if (meta_is_wayland_compositor ())
return META_TYPE_MONITOR_MANAGER;
return META_TYPE_MONITOR_MANAGER_DUMMY;
else
return META_TYPE_MONITOR_MANAGER_XRANDR;
}
@ -379,7 +195,7 @@ get_default_backend (void)
/* 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;
return META_TYPE_MONITOR_MANAGER_DUMMY;
}
#endif
@ -573,6 +389,20 @@ meta_monitor_manager_get_property (GObject *object,
}
}
static GBytes *
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
{
return NULL;
}
static char *
meta_monitor_manager_real_get_edid_file (MetaMonitorManager *manager,
MetaOutput *output)
{
return NULL;
}
static void
meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
{
@ -584,10 +414,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
object_class->dispose = meta_monitor_manager_dispose;
object_class->finalize = meta_monitor_manager_finalize;
klass->read_current = read_current_dummy;
klass->apply_configuration = apply_config_dummy;
klass->get_edid_file = get_edid_file_dummy;
klass->read_edid = read_edid_dummy;
klass->get_edid_file = meta_monitor_manager_real_get_edid_file;
klass->read_edid = meta_monitor_manager_real_read_edid;
signals[CONFIRM_DISPLAY_CHANGE] =
g_signal_new ("confirm-display-change",

View File

@ -43,9 +43,9 @@
#include "stack-tracker.h"
#include "ui.h"
#include <wayland-server.h>
#include "meta-xrandr-shared.h"
#include "meta-dbus-xrandr.h"
#include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h"
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
typedef struct _MetaMonitorManager MetaMonitorManager;
@ -227,8 +227,6 @@ struct _MetaMonitorManager
CRTCs refer to stuff that can drive outputs
(like encoders, but less tied to the HW),
while monitor_infos refer to logical ones.
See also the comment in monitor-private.h
*/
MetaOutput *outputs;
unsigned int n_outputs;
@ -335,57 +333,6 @@ void meta_monitor_manager_apply_configuration (MetaMonitorManager
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
gboolean ok);
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
GType meta_monitor_manager_xrandr_get_type (void);
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
GType meta_monitor_manager_kms_get_type (void);
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_default (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_update_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_crtc_info_free (MetaCRTCInfo *info);
void meta_output_info_free (MetaOutputInfo *info);

View File

@ -0,0 +1,443 @@
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gbm.h>
#include "display-private.h"
#include "meta-cursor-tracker-native.h"
#include "meta-cursor-tracker-private.h"
#include "meta-monitor-manager.h"
#include "meta-cursor-private.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorTrackerNative
{
MetaCursorTracker parent;
gboolean has_hw_cursor;
int current_x, current_y;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
CoglPipeline *pipeline;
int drm_fd;
struct gbm_device *gbm;
};
struct _MetaCursorTrackerNativeClass
{
MetaCursorTrackerClass parent_class;
};
G_DEFINE_TYPE (MetaCursorTrackerNative, meta_cursor_tracker_native, META_TYPE_CURSOR_TRACKER);
static void
meta_cursor_tracker_native_load_cursor_pixels (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t format)
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
if (!self->gbm)
return;
meta_cursor_reference_load_gbm_buffer (cursor,
self->gbm,
pixels,
width, height, rowstride,
format);
}
static void
meta_cursor_tracker_native_load_cursor_buffer (MetaCursorTracker *tracker,
MetaCursorReference *cursor,
struct wl_resource *buffer)
{
struct wl_shm_buffer *shm_buffer;
int width, height;
width = cogl_texture_get_width (COGL_TEXTURE (cursor->image.texture));
height = cogl_texture_get_height (COGL_TEXTURE (cursor->image.texture));
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
uint32_t gbm_format;
uint8_t *pixels = wl_shm_buffer_get_data (shm_buffer);
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
gbm_format = GBM_FORMAT_ARGB8888;
}
meta_cursor_tracker_native_load_cursor_pixels (tracker,
cursor,
pixels,
width,
height,
rowstride,
gbm_format);
}
else
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
if (!self->gbm)
return;
meta_cursor_reference_import_gbm_buffer (cursor, self->gbm, buffer, width, height);
}
}
static void
set_crtc_has_hw_cursor (MetaCursorTrackerNative *self,
MetaCRTC *crtc,
gboolean has)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
if (has)
{
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (displayed_cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (self->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
crtc->has_hw_cursor = TRUE;
}
else
{
drmModeSetCursor2 (self->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
crtc->has_hw_cursor = FALSE;
}
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorTrackerNative *self)
{
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
if (!self->has_hw_cursor)
return;
/* Go through the new list of monitors, find out where the cursor is */
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&self->current_rect, rect);
/* Need to do it unconditionally here, our tracking is
wrong because we reloaded the CRTCs */
set_crtc_has_hw_cursor (self, &crtcs[i], has);
}
}
static gboolean
should_have_hw_cursor (MetaCursorTrackerNative *self)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
if (tracker->displayed_cursor)
return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
else
return FALSE;
}
static void
update_hw_cursor (MetaCursorTrackerNative *self)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
gboolean enabled;
enabled = should_have_hw_cursor (self);
self->has_hw_cursor = enabled;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = enabled && meta_rectangle_overlap (&self->current_rect, rect);
if (has || crtcs[i].has_hw_cursor)
set_crtc_has_hw_cursor (self, &crtcs[i], has);
}
}
static void
move_hw_cursor (MetaCursorTrackerNative *self)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
g_assert (self->has_hw_cursor);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&self->current_rect, rect);
if (has != crtcs[i].has_hw_cursor)
set_crtc_has_hw_cursor (self, &crtcs[i], has);
if (has)
drmModeMoveCursor (self->drm_fd, crtcs[i].crtc_id,
self->current_rect.x - rect->x,
self->current_rect.y - rect->y);
}
}
static void
queue_redraw (MetaCursorTrackerNative *self)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
cairo_rectangle_int_t clip;
/* Clear the location the cursor was at before, if we need to. */
if (self->previous_is_valid)
{
clip.x = self->previous_rect.x;
clip.y = self->previous_rect.y;
clip.width = self->previous_rect.width;
clip.height = self->previous_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
self->previous_is_valid = FALSE;
}
if (self->has_hw_cursor || !tracker->displayed_cursor)
return;
clip.x = self->current_rect.x;
clip.y = self->current_rect.y;
clip.width = self->current_rect.width;
clip.height = self->current_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
}
static void
meta_cursor_tracker_native_sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
MetaCursorReference *displayed_cursor;
displayed_cursor = tracker->displayed_cursor;
if (displayed_cursor)
{
CoglTexture *texture;
int hot_x, hot_y;
texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
self->current_rect.x = self->current_x - hot_x;
self->current_rect.y = self->current_y - hot_y;
self->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
self->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
cogl_pipeline_set_layer_texture (self->pipeline, 0, NULL);
self->current_rect.x = 0;
self->current_rect.y = 0;
self->current_rect.width = 0;
self->current_rect.height = 0;
}
update_hw_cursor (self);
if (self->has_hw_cursor)
move_hw_cursor (self);
else
queue_redraw (self);
}
static void
meta_cursor_tracker_native_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
ClutterDeviceManager *cmanager;
ClutterInputDevice *cdevice;
ClutterPoint point;
/* On wayland we can't use GDK, because that only sees the events we
* forward to xwayland.
*/
cmanager = clutter_device_manager_get_default ();
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);
}
static void
meta_cursor_tracker_native_finalize (GObject *object)
{
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (object);
if (self->pipeline)
cogl_object_unref (self->pipeline);
if (self->gbm)
gbm_device_destroy (self->gbm);
G_OBJECT_CLASS (meta_cursor_tracker_native_parent_class)->finalize (object);
}
static void
meta_cursor_tracker_native_class_init (MetaCursorTrackerNativeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaCursorTrackerClass *cursor_tracker_class = META_CURSOR_TRACKER_CLASS (klass);
object_class->finalize = meta_cursor_tracker_native_finalize;
cursor_tracker_class->get_pointer = meta_cursor_tracker_native_get_pointer;
cursor_tracker_class->sync_cursor = meta_cursor_tracker_native_sync_cursor;
cursor_tracker_class->load_cursor_pixels = meta_cursor_tracker_native_load_cursor_pixels;
cursor_tracker_class->load_cursor_buffer = meta_cursor_tracker_native_load_cursor_buffer;
}
static void
meta_cursor_tracker_native_init (MetaCursorTrackerNative *self)
{
MetaWaylandCompositor *compositor;
CoglContext *ctx;
MetaMonitorManager *monitors;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
self->pipeline = cogl_pipeline_new (ctx);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = META_CURSOR_TRACKER (self);
meta_cursor_tracker_native_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
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
G_CALLBACK (on_monitors_changed), self, 0);
}
void
meta_cursor_tracker_native_update_position (MetaCursorTrackerNative *self,
int new_x,
int new_y)
{
self->current_x = new_x;
self->current_y = new_y;
_meta_cursor_tracker_sync_cursor (META_CURSOR_TRACKER (self));
}
void
meta_cursor_tracker_native_paint (MetaCursorTrackerNative *self)
{
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
if (self->has_hw_cursor || !tracker->displayed_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
self->pipeline,
self->current_rect.x,
self->current_rect.y,
self->current_rect.x +
self->current_rect.width,
self->current_rect.y +
self->current_rect.height);
self->previous_rect = self->current_rect;
self->previous_is_valid = TRUE;
}
void
meta_cursor_tracker_native_force_update (MetaCursorTrackerNative *self)
{
_meta_cursor_tracker_sync_cursor (META_CURSOR_TRACKER (self));
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_CURSOR_TRACKER_NATIVE_H
#define META_CURSOR_TRACKER_NATIVE_H
#include <glib-object.h>
#include <meta/meta-cursor-tracker.h>
#define META_TYPE_CURSOR_TRACKER_NATIVE (meta_cursor_tracker_native_get_type ())
#define META_CURSOR_TRACKER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNative))
#define META_CURSOR_TRACKER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNativeClass))
#define META_IS_CURSOR_TRACKER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER_NATIVE))
#define META_IS_CURSOR_TRACKER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER_NATIVE))
#define META_CURSOR_TRACKER_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNativeClass))
typedef struct _MetaCursorTrackerNative MetaCursorTrackerNative;
typedef struct _MetaCursorTrackerNativeClass MetaCursorTrackerNativeClass;
GType meta_cursor_tracker_native_get_type (void);
void meta_cursor_tracker_native_update_position (MetaCursorTrackerNative *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_native_paint (MetaCursorTrackerNative *tracker);
void meta_cursor_tracker_native_force_update (MetaCursorTrackerNative *tracker);
#endif /* META_CURSOR_TRACKER_NATIVE_H */

View File

@ -0,0 +1,219 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-native.h"
#include "meta-idle-monitor-private.h"
#include <meta/util.h>
#include "display-private.h"
#include <string.h>
struct _MetaIdleMonitorNative
{
MetaIdleMonitor parent;
guint64 last_event_time;
};
struct _MetaIdleMonitorNativeClass
{
MetaIdleMonitorClass parent_class;
};
typedef struct {
MetaIdleMonitorWatch base;
GSource *timeout_source;
} MetaIdleMonitorWatchNative;
G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR)
static gint64
meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static gboolean
native_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatchNative *watch_native = user_data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
_meta_idle_monitor_watch_fire (watch);
g_source_set_ready_time (watch_native->timeout_source, -1);
return TRUE;
}
static GSourceFuncs native_source_funcs = {
NULL, /* prepare */
NULL, /* check */
native_dispatch_timeout,
NULL, /* finalize */
};
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatchNative *watch_native = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
MetaIdleMonitor *monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch_native->timeout_source != NULL)
g_source_destroy (watch_native->timeout_source);
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatchNative, watch_native);
}
static MetaIdleMonitorWatch *
meta_idle_monitor_native_make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatchNative *watch_native;
MetaIdleMonitorWatch *watch;
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
watch_native = g_slice_new0 (MetaIdleMonitorWatchNative);
watch = (MetaIdleMonitorWatch *) watch_native;
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (timeout_msec != 0)
{
GSource *source = g_source_new (&native_source_funcs, sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000);
g_source_attach (source, NULL);
g_source_unref (source);
watch_native->timeout_source = source;
}
return watch;
}
static void
meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass)
{
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime;
idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch;
}
static void
meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
}
typedef struct {
MetaIdleMonitorNative *monitor_native;
GList *fired_watches;
} CheckNativeClosure;
static gboolean
check_native_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitorWatchNative *watch_native = value;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
CheckNativeClosure *closure = user_data;
gboolean steal;
if (watch->timeout_msec == 0)
{
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
steal = TRUE;
}
else
{
g_source_set_ready_time (watch_native->timeout_source,
closure->monitor_native->last_event_time +
watch->timeout_msec * 1000);
steal = FALSE;
}
return steal;
}
static void
fire_native_watch (gpointer watch,
gpointer data)
{
_meta_idle_monitor_watch_fire (watch);
}
void
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
CheckNativeClosure closure;
monitor_native->last_event_time = g_get_monotonic_time ();
closure.monitor_native = monitor_native;
closure.fired_watches = NULL;
g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure);
g_list_foreach (closure.fired_watches, fire_native_watch, NULL);
g_list_free (closure.fired_watches);
}

View File

@ -0,0 +1,43 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_NATIVE_H
#define META_IDLE_MONITOR_NATIVE_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#define META_TYPE_IDLE_MONITOR_NATIVE (meta_idle_monitor_native_get_type ())
#define META_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative))
#define META_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
#define META_IS_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE))
#define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_NATIVE))
#define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
typedef struct _MetaIdleMonitorNative MetaIdleMonitorNative;
typedef struct _MetaIdleMonitorNativeClass MetaIdleMonitorNativeClass;
GType meta_idle_monitor_native_get_type (void);
void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor);
#endif /* META_IDLE_MONITOR_NATIVE_H */

View File

@ -23,6 +23,8 @@
#include "config.h"
#include "meta-monitor-manager-kms.h"
#include <string.h>
#include <stdlib.h>
#include <clutter/clutter.h>
@ -36,7 +38,6 @@
#include <meta/main.h>
#include <meta/errors.h>
#include "monitor-private.h"
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)

View File

@ -0,0 +1,40 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_MANAGER_KMS_H
#define META_MONITOR_MANAGER_KMS_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
GType meta_monitor_manager_kms_get_type (void);
#endif /* META_MONITOR_MANAGER_KMS_H */

View File

@ -42,8 +42,9 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "meta-wayland-private.h"
#include "wayland/meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include "meta-cursor-tracker-native.h"
#include "meta-weston-launch.h"
struct _MetaLauncher
@ -219,7 +220,7 @@ meta_launcher_enter (MetaLauncher *launcher)
* update. */
clutter_actor_queue_redraw (compositor->stage);
meta_cursor_tracker_force_update (compositor->seat->cursor_tracker);
meta_cursor_tracker_native_force_update (META_CURSOR_TRACKER_NATIVE (compositor->seat->cursor_tracker));
}
}

View File

@ -0,0 +1,138 @@
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdkx.h>
#include <meta/errors.h>
#include "display-private.h"
#include "meta-cursor-tracker-x11.h"
#include "meta-cursor-tracker-private.h"
#include "meta-cursor-private.h"
struct _MetaCursorTrackerX11
{
MetaCursorTracker parent;
};
struct _MetaCursorTrackerX11Class
{
MetaCursorTrackerClass parent_class;
};
G_DEFINE_TYPE (MetaCursorTrackerX11, meta_cursor_tracker_x11, META_TYPE_CURSOR_TRACKER);
static void
meta_cursor_tracker_x11_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
GdkScreen *gscreen;
/* We can't use the clutter interface when not running as a wayland
* compositor, because we need to query the server, rather than
* using the last cached value.
*/
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
gdk_device_get_position (gdevice, &gscreen, x, y);
if (mods)
gdk_device_get_state (gdevice,
gdk_screen_get_root_window (gscreen),
NULL, (GdkModifierType*)mods);
}
static void
meta_cursor_tracker_x11_sync_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
meta_error_trap_push (display);
if (tracker->is_showing)
XFixesShowCursor (display->xdisplay,
DefaultRootWindow (display->xdisplay));
else
XFixesHideCursor (display->xdisplay,
DefaultRootWindow (display->xdisplay));
meta_error_trap_pop (display);
}
static void
meta_cursor_tracker_x11_ensure_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
MetaCursorReference *cursor;
if (tracker->has_window_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
if (!cursor_image)
return;
cursor = meta_cursor_reference_from_xfixes_cursor_image (cursor_image);
_meta_cursor_tracker_set_window_cursor (tracker, TRUE, cursor);
XFree (cursor_image);
}
static void
meta_cursor_tracker_x11_class_init (MetaCursorTrackerX11Class *klass)
{
MetaCursorTrackerClass *cursor_tracker_class = META_CURSOR_TRACKER_CLASS (klass);
cursor_tracker_class->get_pointer = meta_cursor_tracker_x11_get_pointer;
cursor_tracker_class->sync_cursor = meta_cursor_tracker_x11_sync_cursor;
cursor_tracker_class->ensure_cursor = meta_cursor_tracker_x11_ensure_cursor;
}
static void
meta_cursor_tracker_x11_init (MetaCursorTrackerX11 *self)
{
MetaDisplay *display = meta_get_display ();
XFixesSelectCursorInput (display->xdisplay,
DefaultRootWindow (display->xdisplay),
XFixesDisplayCursorNotifyMask);
}
gboolean
meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
_meta_cursor_tracker_set_window_cursor (META_CURSOR_TRACKER (tracker), FALSE, NULL);
return TRUE;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_CURSOR_TRACKER_X11_H
#define META_CURSOR_TRACKER_X11_H
#include <glib-object.h>
#include <meta/meta-cursor-tracker.h>
#define META_TYPE_CURSOR_TRACKER_X11 (meta_cursor_tracker_x11_get_type ())
#define META_CURSOR_TRACKER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11))
#define META_CURSOR_TRACKER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11Class))
#define META_IS_CURSOR_TRACKER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER_X11))
#define META_IS_CURSOR_TRACKER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER_X11))
#define META_CURSOR_TRACKER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11Class))
typedef struct _MetaCursorTrackerX11 MetaCursorTrackerX11;
typedef struct _MetaCursorTrackerX11Class MetaCursorTrackerX11Class;
GType meta_cursor_tracker_x11_get_type (void);
gboolean
meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker,
XEvent *xevent);
#endif /* META_CURSOR_TRACKER_X11_H */

View File

@ -0,0 +1,366 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-xsync.h"
#include "meta-idle-monitor-private.h"
#include <meta/util.h>
#include "display-private.h"
#include <string.h>
struct _MetaIdleMonitorXSync
{
MetaIdleMonitor parent;
GHashTable *alarms;
Display *display;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
};
struct _MetaIdleMonitorXSyncClass
{
MetaIdleMonitorClass parent_class;
};
typedef struct {
MetaIdleMonitorWatch base;
XSyncAlarm xalarm;
} MetaIdleMonitorWatchXSync;
G_DEFINE_TYPE (MetaIdleMonitorXSync, meta_idle_monitor_xsync, META_TYPE_IDLE_MONITOR)
static gint64
_xsyncvalue_to_int64 (XSyncValue value)
{
return ((guint64) XSyncValueHigh32 (value)) << 32
| (guint64) XSyncValueLow32 (value);
}
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
static XSyncAlarm
_xsync_alarm_set (MetaIdleMonitorXSync *monitor_xsync,
XSyncTestType test_type,
guint64 interval,
gboolean want_events)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
guint flags;
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
XSyncIntToValue (&delta, 0);
attr.trigger.counter = monitor_xsync->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = want_events;
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
attr.trigger.test_type = test_type;
return XSyncCreateAlarm (monitor_xsync->display, flags, &attr);
}
static void
ensure_alarm_rescheduled (Display *dpy,
XSyncAlarm alarm)
{
XSyncAlarmAttributes attr;
/* Some versions of Xorg have an issue where alarms aren't
* always rescheduled. Calling XSyncChangeAlarm, even
* without any attributes, will reschedule the alarm. */
XSyncChangeAlarm (dpy, alarm, 0, &attr);
}
static void
set_alarm_enabled (Display *dpy,
XSyncAlarm alarm,
gboolean enabled)
{
XSyncAlarmAttributes attr;
attr.events = enabled;
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static void
check_x11_watch (gpointer data,
gpointer user_data)
{
MetaIdleMonitorWatchXSync *watch_xsync = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
XSyncAlarm alarm = (XSyncAlarm) user_data;
if (watch_xsync->xalarm != alarm)
return;
_meta_idle_monitor_watch_fire (watch);
}
static char *
counter_name_for_device (int device_id)
{
if (device_id > 0)
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
return g_strdup ("IDLETIME");
}
static XSyncCounter
find_idletime_counter (MetaIdleMonitorXSync *monitor_xsync)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
int i;
int ncounters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
char *counter_name;
counter_name = counter_name_for_device (monitor->device_id);
counters = XSyncListSystemCounters (monitor_xsync->display, &ncounters);
for (i = 0; i < ncounters; i++)
{
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
g_free (counter_name);
return counter;
}
static void
init_xsync (MetaIdleMonitorXSync *monitor_xsync)
{
monitor_xsync->counter = find_idletime_counter (monitor_xsync);
/* IDLETIME counter not found? */
if (monitor_xsync->counter == None)
{
g_warning ("IDLETIME counter not found\n");
return;
}
monitor_xsync->user_active_alarm = _xsync_alarm_set (monitor_xsync, XSyncNegativeTransition, 1, FALSE);
}
static void
meta_idle_monitor_xsync_dispose (GObject *object)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
if (monitor_xsync->user_active_alarm != None)
{
XSyncDestroyAlarm (monitor_xsync->display, monitor_xsync->user_active_alarm);
monitor_xsync->user_active_alarm = None;
}
g_clear_pointer (&monitor_xsync->alarms, g_hash_table_destroy);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->dispose (object);
}
static void
meta_idle_monitor_xsync_constructed (GObject *object)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
g_assert (!meta_is_wayland_compositor ());
monitor_xsync->display = meta_get_display ()->xdisplay;
init_xsync (monitor_xsync);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
}
static gint64
meta_idle_monitor_xsync_get_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncValue value;
if (!XSyncQueryCounter (monitor_xsync->display, monitor_xsync->counter, &value))
return -1;
return _xsyncvalue_to_int64 (value);
}
static gboolean
fire_watch_idle (gpointer data)
{
MetaIdleMonitorWatch *watch = data;
watch->idle_source_id = 0;
_meta_idle_monitor_watch_fire (watch);
return FALSE;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatchXSync *watch_xsync = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
MetaIdleMonitor *monitor = watch->monitor;
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch_xsync->xalarm != monitor_xsync->user_active_alarm &&
watch_xsync->xalarm != None)
{
XSyncDestroyAlarm (monitor_xsync->display, watch_xsync->xalarm);
g_hash_table_remove (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
}
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatchXSync, watch_xsync);
}
static MetaIdleMonitorWatch *
meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
MetaIdleMonitorWatchXSync *watch_xsync;
MetaIdleMonitorWatch *watch;
watch_xsync = g_slice_new0 (MetaIdleMonitorWatchXSync);
watch = (MetaIdleMonitorWatch *) watch_xsync;
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (monitor_xsync->user_active_alarm != None)
{
if (timeout_msec != 0)
{
watch_xsync->xalarm = _xsync_alarm_set (monitor_xsync, XSyncPositiveTransition, timeout_msec, TRUE);
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
}
else
{
watch_xsync->xalarm = monitor_xsync->user_active_alarm;
set_alarm_enabled (monitor_xsync->display, monitor_xsync->user_active_alarm, TRUE);
}
}
return watch;
}
static void
meta_idle_monitor_xsync_class_init (MetaIdleMonitorXSyncClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
object_class->dispose = meta_idle_monitor_xsync_dispose;
object_class->constructed = meta_idle_monitor_xsync_constructed;
idle_monitor_class->get_idletime = meta_idle_monitor_xsync_get_idletime;
idle_monitor_class->make_watch = meta_idle_monitor_xsync_make_watch;
}
static void
meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
}
void
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncAlarm alarm;
GList *watches;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
return;
alarm = alarm_event->alarm;
has_alarm = FALSE;
if (alarm == monitor_xsync->user_active_alarm)
{
set_alarm_enabled (monitor_xsync->display,
alarm,
FALSE);
has_alarm = TRUE;
}
else if (g_hash_table_contains (monitor_xsync->alarms, (gpointer) alarm))
{
ensure_alarm_rescheduled (monitor_xsync->display,
alarm);
has_alarm = TRUE;
}
if (has_alarm)
{
watches = g_hash_table_get_values (monitor->watches);
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
g_list_free (watches);
}
}

View File

@ -0,0 +1,49 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_XSYNC_H
#define META_IDLE_MONITOR_XSYNC_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#define META_TYPE_IDLE_MONITOR_XSYNC (meta_idle_monitor_xsync_get_type ())
#define META_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSync))
#define META_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
#define META_IS_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_XSYNC))
#define META_IS_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_XSYNC))
#define META_IDLE_MONITOR_XSYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
typedef struct _MetaIdleMonitorXSync MetaIdleMonitorXSync;
typedef struct _MetaIdleMonitorXSyncClass MetaIdleMonitorXSyncClass;
GType meta_idle_monitor_xsync_get_type (void);
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *xevent);
void meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent);
#endif /* META_IDLE_MONITOR_XSYNC_H */

View File

@ -25,6 +25,8 @@
#include "config.h"
#include "meta-monitor-manager-xrandr.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
@ -36,9 +38,8 @@
#include <meta/main.h>
#include <meta/errors.h>
#include "monitor-private.h"
#include "edid.h"
#include "meta-monitor-config.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)

View File

@ -0,0 +1,40 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_MANAGER_XRANDR_H
#define META_MONITOR_MANAGER_XRANDR_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
GType meta_monitor_manager_xrandr_get_type (void);
#endif /* META_MONITOR_MANAGER_XRANDR_H */

View File

@ -11,8 +11,6 @@
#include "meta-window-actor-private.h"
#include <clutter/clutter.h>
typedef struct _MetaCompScreen MetaCompScreen;
struct _MetaCompositor
{
MetaDisplay *display;
@ -24,11 +22,6 @@ struct _MetaCompositor
guint server_time_is_monotonic_time : 1;
guint no_mipmaps : 1;
};
struct _MetaCompScreen
{
MetaScreen *screen;
ClutterActor *stage, *window_group, *top_window_group;
ClutterActor *background_actor;
@ -50,13 +43,13 @@ struct _MetaCompScreen
/* Wait 2ms after vblank before starting to draw next frame */
#define META_SYNC_DELAY 2
void meta_switch_workspace_completed (MetaScreen *screen);
void meta_switch_workspace_completed (MetaCompositor *compositor);
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
gboolean meta_begin_modal_for_plugin (MetaCompositor *compositor,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp);
void meta_end_modal_for_plugin (MetaScreen *screen,
void meta_end_modal_for_plugin (MetaCompositor *compositor,
MetaPlugin *plugin,
guint32 timestamp);

View File

@ -99,36 +99,34 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
return (major > maj || (major == maj && minor >= min));
}
static void sync_actor_stacking (MetaCompScreen *info);
static void sync_actor_stacking (MetaCompositor *compositor);
static void
meta_finish_workspace_switch (MetaCompScreen *info)
meta_finish_workspace_switch (MetaCompositor *compositor)
{
GList *l;
/* Finish hiding and showing actors for the new workspace */
for (l = info->windows; l; l = l->next)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_sync_visibility (l->data);
/* Fix up stacking order. */
sync_actor_stacking (info);
sync_actor_stacking (compositor);
}
void
meta_switch_workspace_completed (MetaScreen *screen)
meta_switch_workspace_completed (MetaCompositor *compositor)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
/* FIXME -- must redo stacking order */
info->switch_workspace_in_progress--;
if (info->switch_workspace_in_progress < 0)
compositor->switch_workspace_in_progress--;
if (compositor->switch_workspace_in_progress < 0)
{
g_warning ("Error in workspace_switch accounting!");
info->switch_workspace_in_progress = 0;
compositor->switch_workspace_in_progress = 0;
}
if (!info->switch_workspace_in_progress)
meta_finish_workspace_switch (info);
if (!compositor->switch_workspace_in_progress)
meta_finish_workspace_switch (compositor);
}
void
@ -147,17 +145,17 @@ process_damage (MetaCompositor *compositor,
}
static Window
get_output_window (MetaScreen *screen)
get_output_window (MetaCompositor *compositor)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window output, xroot;
MetaDisplay *display = compositor->display;
Display *xdisplay = display->xdisplay;
Window output, xroot;
XWindowAttributes attr;
long event_mask;
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
xroot = meta_screen_get_xroot (screen);
xroot = display->screen->xroot;
output = XCompositeGetOverlayWindow (xdisplay, xroot);
meta_core_add_old_event_mask (xdisplay, output, &mask);
@ -182,6 +180,13 @@ get_output_window (MetaScreen *screen)
return output;
}
/* compat helper */
static MetaCompositor *
get_compositor_for_screen (MetaScreen *screen)
{
return screen->display->compositor;
}
/**
* meta_get_stage_for_screen:
* @screen: a #MetaScreen
@ -191,12 +196,8 @@ get_output_window (MetaScreen *screen)
ClutterActor *
meta_get_stage_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->stage;
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->stage;
}
/**
@ -208,12 +209,8 @@ meta_get_stage_for_screen (MetaScreen *screen)
ClutterActor *
meta_get_window_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->window_group;
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->window_group;
}
/**
@ -225,12 +222,8 @@ meta_get_window_group_for_screen (MetaScreen *screen)
ClutterActor *
meta_get_top_window_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->top_window_group;
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->top_window_group;
}
/**
@ -242,12 +235,8 @@ meta_get_top_window_group_for_screen (MetaScreen *screen)
GList *
meta_get_window_actors (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->windows;
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->windows;
}
void
@ -261,10 +250,10 @@ 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));
MetaDisplay *display = screen->display;
MetaCompositor *compositor = display->compositor;
Display *xdpy = meta_display_get_xdisplay (display);
Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);
@ -273,7 +262,7 @@ meta_set_stage_input_region (MetaScreen *screen,
* 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);
XFixesSetWindowShapeRegion (xdpy, compositor->output, ShapeInput, 0, 0, region);
}
}
@ -338,15 +327,14 @@ meta_stage_is_focused (MetaScreen *screen)
}
static gboolean
begin_modal_x11 (MetaScreen *screen,
begin_modal_x11 (MetaCompositor *compositor,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaDisplay *display = compositor->display;
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
int result;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
@ -411,7 +399,7 @@ begin_modal_x11 (MetaScreen *screen,
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
meta_begin_modal_for_plugin (MetaCompositor *compositor,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
@ -420,18 +408,17 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
* are significant differences in how we handle grabs that make it difficult to
* merge the two.
*/
MetaDisplay *display = meta_screen_get_display (screen);
MetaDisplay *display = compositor->display;
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
if (!meta_is_wayland_compositor ())
if (!begin_modal_x11 (screen, plugin, options, timestamp))
if (!begin_modal_x11 (compositor, plugin, options, timestamp))
return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL;
display->grab_screen = screen;
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
@ -442,18 +429,17 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
}
void
meta_end_modal_for_plugin (MetaScreen *screen,
meta_end_modal_for_plugin (MetaCompositor *compositor,
MetaPlugin *plugin,
guint32 timestamp)
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaDisplay *display = compositor->display;
Display *xdpy = meta_display_get_xdisplay (display);
g_return_if_fail (is_modal (display));
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_screen = NULL;
display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE;
@ -472,10 +458,10 @@ static void
after_stage_paint (ClutterStage *stage,
gpointer data)
{
MetaCompScreen *info = (MetaCompScreen*) data;
MetaCompositor *compositor = data;
GList *l;
for (l = info->windows; l; l = l->next)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_post_paint (l->data);
if (meta_is_wayland_compositor ())
@ -483,8 +469,7 @@ after_stage_paint (ClutterStage *stage,
}
static void
redirect_windows (MetaCompositor *compositor,
MetaScreen *screen)
redirect_windows (MetaScreen *screen)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
@ -527,48 +512,35 @@ redirect_windows (MetaCompositor *compositor,
}
void
meta_compositor_manage_screen (MetaCompositor *compositor,
MetaScreen *screen)
meta_compositor_manage (MetaCompositor *compositor)
{
MetaCompScreen *info;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwin = None;
gint width, height;
MetaDisplay *display = compositor->display;
Display *xdisplay = display->xdisplay;
MetaScreen *screen = display->screen;
Window xwin = 0;
gint width, height;
MetaWaylandCompositor *wayland_compositor;
/* Check if the screen is already managed */
if (meta_screen_get_compositor_data (screen))
return;
info = g_new0 (MetaCompScreen, 1);
info->screen = screen;
meta_screen_set_compositor_data (screen, info);
info->output = None;
info->windows = NULL;
meta_screen_set_cm_selection (screen);
meta_screen_set_cm_selection (display->screen);
/* We will have already created a stage if running as a wayland
* compositor... */
if (meta_is_wayland_compositor ())
{
wayland_compositor = meta_wayland_compositor_get_default ();
info->stage = wayland_compositor->stage;
compositor->stage = wayland_compositor->stage;
meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (info->stage, width, height);
clutter_actor_set_size (compositor->stage, width, height);
}
else
{
info->stage = clutter_stage_new ();
compositor->stage = clutter_stage_new ();
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (info->stage);
clutter_actor_realize (compositor->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XResizeWindow (xdisplay, xwin, width, height);
@ -602,30 +574,30 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
}
}
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
after_stage_paint,
info,
compositor,
NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
info->window_group = meta_window_group_new (screen);
info->top_window_group = meta_window_group_new (screen);
compositor->window_group = meta_window_group_new (screen);
compositor->top_window_group = meta_window_group_new (screen);
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
clutter_actor_add_child (compositor->stage, compositor->window_group);
clutter_actor_add_child (compositor->stage, compositor->top_window_group);
if (meta_is_wayland_compositor ())
{
/* NB: When running as a wayland compositor we don't need an X
* composite overlay window, and we don't need to play any input
* region tricks to redirect events into clutter. */
info->output = None;
compositor->output = None;
}
else
{
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
compositor->output = get_output_window (compositor);
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
meta_empty_stage_input_region (screen);
@ -637,28 +609,27 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
* because the X server will destroy the overlay window
* when the last client using it exits.
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, None);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
XMapWindow (xdisplay, compositor->output);
}
redirect_windows (compositor, screen);
redirect_windows (display->screen);
info->plugin_mgr = meta_plugin_manager_new (screen);
compositor->plugin_mgr = meta_plugin_manager_new (compositor);
}
void
meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen)
meta_compositor_unmanage (MetaCompositor *compositor)
{
if (!meta_is_wayland_compositor ())
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
MetaDisplay *display = compositor->display;
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = display->screen->xroot;
/* This is the most important part of cleanup - we have to do this
* before giving up the window manager selection or the next
@ -669,7 +640,7 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
/**
* meta_shape_cow_for_window:
* @screen: A #MetaScreen
* @compositor: A #MetaCompositor
* @window: (allow-none): A #MetaWindow to shape the COW for
*
* Sets an bounding shape on the COW so that the given window
@ -679,14 +650,14 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
* of the COW, letting the raw window be seen through below.
*/
static void
meta_shape_cow_for_window (MetaScreen *screen,
meta_shape_cow_for_window (MetaCompositor *compositor,
MetaWindow *window)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
MetaDisplay *display = compositor->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (window == NULL)
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, None);
else
{
XserverRegion output_region;
@ -701,7 +672,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
window_bounds.width = rect.width;
window_bounds.height = rect.height;
meta_screen_get_size (screen, &width, &height);
meta_screen_get_size (display->screen, &width, &height);
screen_rect.x = 0;
screen_rect.y = 0;
screen_rect.width = width;
@ -710,47 +681,45 @@ meta_shape_cow_for_window (MetaScreen *screen,
output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);
XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, output_region);
XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, output_region);
XFixesDestroyRegion (xdisplay, output_region);
}
}
static void
set_unredirected_window (MetaCompScreen *info,
set_unredirected_window (MetaCompositor *compositor,
MetaWindow *window)
{
if (info->unredirected_window == window)
if (compositor->unredirected_window == window)
return;
if (info->unredirected_window != NULL)
if (compositor->unredirected_window != NULL)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (info->unredirected_window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (compositor->unredirected_window));
meta_window_actor_set_unredirected (window_actor, FALSE);
}
info->unredirected_window = window;
compositor->unredirected_window = window;
if (info->unredirected_window != NULL)
if (compositor->unredirected_window != NULL)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (info->unredirected_window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (compositor->unredirected_window));
meta_window_actor_set_unredirected (window_actor, TRUE);
}
meta_shape_cow_for_window (info->screen, info->unredirected_window);
meta_shape_cow_for_window (compositor, compositor->unredirected_window);
}
void
meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window)
{
MetaScreen *screen = meta_window_get_screen (window);
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = compositor->display;
meta_error_trap_push (display);
meta_window_actor_new (window);
sync_actor_stacking (info);
sync_actor_stacking (compositor);
meta_error_trap_pop (display);
}
@ -760,11 +729,9 @@ meta_compositor_remove_window (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info->unredirected_window == window)
set_unredirected_window (info, NULL);
if (compositor->unredirected_window == window)
set_unredirected_window (compositor, NULL);
meta_window_actor_destroy (window_actor);
}
@ -881,11 +848,11 @@ event_is_passive_button_grab (MetaDisplay *display,
* these events by pretending we got an event on the stage window.
*/
static void
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
maybe_spoof_event_as_stage_event (MetaCompositor *compositor,
MetaWindow *window,
XEvent *event)
{
MetaDisplay *display = meta_screen_get_display (info->screen);
MetaDisplay *display = compositor->display;
if (event->type == GenericEvent &&
event->xcookie.extension == display->xinput_opcode)
@ -909,10 +876,10 @@ maybe_spoof_event_as_stage_event (MetaCompScreen *info,
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))
if (meta_ui_window_is_widget (display->screen->ui, device_event->event))
break;
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
break;
@ -935,14 +902,10 @@ meta_compositor_process_event (MetaCompositor *compositor,
MetaWindow *window)
{
MetaDisplay *display = compositor->display;
MetaScreen *screen = display->screens->data;
MetaCompScreen *info;
info = meta_screen_get_compositor_data (screen);
if (is_modal (display) && is_grabbed_event (compositor->display, event))
if (is_modal (display) && is_grabbed_event (display, event))
{
meta_plugin_manager_xevent_filter (info->plugin_mgr, event);
meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event);
/* We always consume events even if the plugin says it didn't handle them;
* exclusive is exclusive */
@ -950,9 +913,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
}
if (!meta_is_wayland_compositor ())
maybe_spoof_event_as_stage_event (info, window, event);
maybe_spoof_event_as_stage_event (compositor, window, event);
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
return TRUE;
if (!meta_is_wayland_compositor () &&
@ -967,7 +930,8 @@ meta_compositor_process_event (MetaCompositor *compositor,
window = meta_display_lookup_x_window (compositor->display, xwin);
}
process_damage (compositor, (XDamageNotifyEvent *) event, window);
if (window)
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
/* Clutter needs to know about MapNotify events otherwise it will
@ -984,11 +948,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
gboolean
meta_compositor_filter_keybinding (MetaCompositor *compositor,
MetaScreen *screen,
MetaKeyBinding *binding)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
return meta_plugin_manager_filter_keybinding (compositor->plugin_mgr, binding);
}
void
@ -1031,40 +993,35 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
void
meta_compositor_switch_workspace (MetaCompositor *compositor,
MetaScreen *screen,
MetaWorkspace *from,
MetaWorkspace *to,
MetaMotionDirection direction)
{
MetaCompScreen *info;
gint to_indx, from_indx;
gint to_indx, from_indx;
info = meta_screen_get_compositor_data (screen);
to_indx = meta_workspace_index (to);
from_indx = meta_workspace_index (from);
if (!info) /* During startup before manage_screen() */
return;
compositor->switch_workspace_in_progress++;
info->switch_workspace_in_progress++;
if (!meta_plugin_manager_switch_workspace (info->plugin_mgr,
from_indx, to_indx,
if (!meta_plugin_manager_switch_workspace (compositor->plugin_mgr,
from_indx,
to_indx,
direction))
{
info->switch_workspace_in_progress--;
compositor->switch_workspace_in_progress--;
/* We have to explicitely call this to fix up stacking order of the
* actors; this is because the abs stacking position of actors does not
* necessarily change during the window hiding/unhiding, only their
* relative position toward the destkop window.
*/
meta_finish_workspace_switch (info);
meta_finish_workspace_switch (compositor);
}
}
static void
sync_actor_stacking (MetaCompScreen *info)
sync_actor_stacking (MetaCompositor *compositor)
{
GList *children;
GList *expected_window_node;
@ -1080,7 +1037,7 @@ sync_actor_stacking (MetaCompScreen *info)
* little effort to make sure we actually need to restack before
* we go ahead and do it */
children = clutter_actor_get_children (info->window_group);
children = clutter_actor_get_children (compositor->window_group);
has_windows = FALSE;
reordered = FALSE;
@ -1092,7 +1049,7 @@ sync_actor_stacking (MetaCompScreen *info)
/* First we collect a list of all backgrounds, and check if they're at the
* bottom. Then we check if the window actors are in the correct sequence */
backgrounds = NULL;
expected_window_node = info->windows;
expected_window_node = compositor->windows;
for (old = children; old != NULL; old = old->next)
{
ClutterActor *actor = old->data;
@ -1130,7 +1087,7 @@ sync_actor_stacking (MetaCompScreen *info)
* We reorder the actors even if they're not parented to the window group,
* to allow stacking to work with intermediate actors (eg during effects)
*/
for (tmp = g_list_last (info->windows); tmp != NULL; tmp = tmp->prev)
for (tmp = g_list_last (compositor->windows); tmp != NULL; tmp = tmp->prev)
{
ClutterActor *actor = tmp->data, *parent;
@ -1153,11 +1110,9 @@ sync_actor_stacking (MetaCompScreen *info)
void
meta_compositor_sync_stack (MetaCompositor *compositor,
MetaScreen *screen,
GList *stack)
{
GList *old_stack;
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
/* This is painful because hidden windows that we are in the process
* of animating out of existence. They'll be at the bottom of the
@ -1167,8 +1122,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
/* Sources: first window is the highest */
stack = g_list_copy (stack); /* The new stack of MetaWindow */
old_stack = g_list_reverse (info->windows); /* The old stack of MetaWindowActor */
info->windows = NULL;
old_stack = g_list_reverse (compositor->windows); /* The old stack of MetaWindowActor */
compositor->windows = NULL;
while (TRUE)
{
@ -1232,13 +1187,13 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
* be at the front of at least one, hopefully it will be
* near the front of the other.)
*/
info->windows = g_list_prepend (info->windows, actor);
compositor->windows = g_list_prepend (compositor->windows, actor);
stack = g_list_remove (stack, window);
old_stack = g_list_remove (old_stack, actor);
}
sync_actor_stacking (info);
sync_actor_stacking (compositor);
}
void
@ -1252,12 +1207,10 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
void
meta_compositor_sync_screen_size (MetaCompositor *compositor,
MetaScreen *screen,
guint width,
guint height)
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = compositor->display;
if (meta_is_wayland_compositor ())
{
@ -1271,23 +1224,21 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
show the right portions on the right screens.
*/
clutter_actor_set_size (info->stage, width, height);
clutter_actor_set_size (compositor->stage, width, height);
}
else
{
Display *xdisplay;
Window xwin;
g_return_if_fail (info);
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XResizeWindow (xdisplay, xwin, width, height);
}
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (screen),
meta_screen_get_screen_number (display->screen),
width, height);
}
@ -1297,7 +1248,7 @@ frame_callback (CoglOnscreen *onscreen,
CoglFrameInfo *frame_info,
void *user_data)
{
MetaCompScreen *info = user_data;
MetaCompositor *compositor = user_data;
GList *l;
if (event == COGL_FRAME_EVENT_COMPLETE)
@ -1328,38 +1279,38 @@ frame_callback (CoglOnscreen *onscreen,
presentation_time = 0;
}
for (l = info->windows; l; l = l->next)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_frame_complete (l->data, frame_info, presentation_time);
}
}
static void
pre_paint_windows (MetaCompScreen *info)
pre_paint_windows (MetaCompositor *compositor)
{
GList *l;
MetaWindowActor *top_window;
if (info->onscreen == NULL)
if (compositor->onscreen == NULL)
{
info->onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer ());
info->frame_closure = cogl_onscreen_add_frame_callback (info->onscreen,
frame_callback,
info,
NULL);
compositor->onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer ());
compositor->frame_closure = cogl_onscreen_add_frame_callback (compositor->onscreen,
frame_callback,
compositor,
NULL);
}
if (info->windows == NULL)
if (compositor->windows == NULL)
return;
top_window = g_list_last (info->windows)->data;
top_window = g_list_last (compositor->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));
compositor->disable_unredirect_count == 0)
set_unredirected_window (compositor, meta_window_actor_get_meta_window (top_window));
else
set_unredirected_window (info, NULL);
set_unredirected_window (compositor, NULL);
for (l = info->windows; l; l = l->next)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data);
}
@ -1367,19 +1318,7 @@ static gboolean
meta_repaint_func (gpointer data)
{
MetaCompositor *compositor = data;
GSList *screens = meta_display_get_screens (compositor->display);
GSList *l;
for (l = screens; l; l = l->next)
{
MetaScreen *screen = l->data;
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
continue;
pre_paint_windows (info);
}
pre_paint_windows (compositor);
return TRUE;
}
@ -1387,20 +1326,10 @@ static void
on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor *compositor)
{
GSList *screens = meta_display_get_screens (compositor->display);
GList *l;
GSList *sl;
for (sl = screens; sl; sl = sl->next)
{
MetaScreen *screen = sl->data;
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
continue;
for (l = info->windows; l; l = l->next)
meta_window_actor_invalidate_shadow (l->data);
}
for (l = compositor->windows; l; l = l->next)
meta_window_actor_invalidate_shadow (l->data);
}
/**
@ -1443,9 +1372,8 @@ meta_compositor_new (MetaDisplay *display)
Window
meta_get_overlay_window (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
return info->output;
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->output;
}
/**
@ -1459,9 +1387,8 @@ meta_get_overlay_window (MetaScreen *screen)
void
meta_disable_unredirect_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info != NULL)
info->disable_unredirect_count = info->disable_unredirect_count + 1;
MetaCompositor *compositor = get_compositor_for_screen (screen);
compositor->disable_unredirect_count++;
}
/**
@ -1474,11 +1401,11 @@ meta_disable_unredirect_for_screen (MetaScreen *screen)
void
meta_enable_unredirect_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info != NULL && info->disable_unredirect_count == 0)
MetaCompositor *compositor = get_compositor_for_screen (screen);
if (compositor->disable_unredirect_count == 0)
g_warning ("Called enable_unredirect_for_screen while unredirection is enabled.");
if (info != NULL && info->disable_unredirect_count > 0)
info->disable_unredirect_count = info->disable_unredirect_count - 1;
if (compositor->disable_unredirect_count > 0)
compositor->disable_unredirect_count--;
}
#define FLASH_TIME_MS 50
@ -1575,20 +1502,16 @@ meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
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);
meta_plugin_manager_show_tile_preview (info->plugin_mgr,
meta_plugin_manager_show_tile_preview (compositor->plugin_mgr,
window, tile_rect, tile_monitor_number);
}
void
meta_compositor_hide_tile_preview (MetaCompositor *compositor,
MetaScreen *screen)
meta_compositor_hide_tile_preview (MetaCompositor *compositor)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
meta_plugin_manager_hide_tile_preview (compositor->plugin_mgr);
}

View File

@ -26,8 +26,6 @@
#include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h>
#include "cogl-utils.h"
@ -755,88 +753,6 @@ set_filename (MetaBackground *self,
priv->filename = g_strdup (filename);
}
static Pixmap
get_still_frame_for_monitor (MetaScreen *screen,
int monitor)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
Pixmap pixmap;
GC gc;
XGCValues values;
MetaRectangle geometry;
int depth;
meta_screen_get_monitor_geometry (screen, monitor, &geometry);
depth = DefaultDepth (xdisplay, meta_screen_get_screen_number (screen));
pixmap = XCreatePixmap (xdisplay,
xroot,
geometry.width, geometry.height, depth);
values.function = GXcopy;
values.plane_mask = AllPlanes;
values.fill_style = FillSolid;
values.subwindow_mode = IncludeInferiors;
gc = XCreateGC (xdisplay,
xroot,
GCFunction | GCPlaneMask | GCFillStyle | GCSubwindowMode,
&values);
XCopyArea (xdisplay,
xroot, pixmap, gc,
geometry.x, geometry.y,
geometry.width, geometry.height,
0, 0);
XFreeGC (xdisplay, gc);
return pixmap;
}
/**
* meta_background_load_still_frame:
* @self: the #MetaBackground
*
* Takes a screenshot of the desktop and uses it as the background
* source.
*/
void
meta_background_load_still_frame (MetaBackground *self)
{
MetaBackgroundPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Pixmap still_frame;
CoglTexture *texture;
CoglContext *context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
GError *error = NULL;
ensure_pipeline (self);
unset_texture (self);
set_style (self, G_DESKTOP_BACKGROUND_STYLE_STRETCHED);
still_frame = get_still_frame_for_monitor (priv->screen, priv->monitor);
XSync (meta_display_get_xdisplay (display), False);
meta_error_trap_push (display);
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (context, still_frame, FALSE, &error));
meta_error_trap_pop (display);
if (error != NULL)
{
g_warning ("Failed to create background texture from pixmap: %s",
error->message);
g_error_free (error);
return;
}
set_texture (self, texture);
}
/**
* meta_background_load_gradient:
* @self: the #MetaBackground

View File

@ -37,7 +37,7 @@ static GType plugin_type = G_TYPE_NONE;
struct MetaPluginManager
{
MetaScreen *screen;
MetaCompositor *compositor;
MetaPlugin *plugin;
};
@ -91,7 +91,7 @@ on_confirm_display_change (MetaMonitorManager *monitors,
}
MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen)
meta_plugin_manager_new (MetaCompositor *compositor)
{
MetaPluginManager *plugin_mgr;
MetaPluginClass *klass;
@ -99,10 +99,10 @@ meta_plugin_manager_new (MetaScreen *screen)
MetaMonitorManager *monitors;
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
plugin_mgr->compositor = compositor;
plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL);
_meta_plugin_set_screen (plugin, screen);
_meta_plugin_set_compositor (plugin, compositor);
klass = META_PLUGIN_GET_CLASS (plugin);
@ -153,7 +153,7 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
MetaDisplay *display = plugin_mgr->compositor->display;
gboolean retval = FALSE;
if (display->display_opening)
@ -213,7 +213,7 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
MetaDisplay *display = plugin_mgr->compositor->display;
gboolean retval = FALSE;
if (display->display_opening)
@ -266,7 +266,7 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
MetaDisplay *display = plugin_mgr->compositor->display;
gboolean retval = FALSE;
if (display->display_opening)
@ -324,7 +324,7 @@ meta_plugin_manager_show_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);
MetaDisplay *display = plugin_mgr->compositor->display;
if (display->display_opening)
return FALSE;
@ -343,7 +343,7 @@ 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);
MetaDisplay *display = plugin_mgr->compositor->display;
if (display->display_opening)
return FALSE;

View File

@ -44,7 +44,7 @@
*/
typedef struct MetaPluginManager MetaPluginManager;
MetaPluginManager * meta_plugin_manager_new (MetaScreen *screen);
MetaPluginManager * meta_plugin_manager_new (MetaCompositor *compositor);
void meta_plugin_manager_load (const gchar *plugin_name);

View File

@ -40,7 +40,7 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "monitor-private.h"
#include "meta-monitor-manager.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
@ -49,7 +49,7 @@ G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
struct _MetaPluginPrivate
{
MetaScreen *screen;
MetaCompositor *compositor;
};
static void
@ -101,9 +101,8 @@ void
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
meta_switch_workspace_completed (screen);
meta_switch_workspace_completed (priv->compositor);
}
static void
@ -177,7 +176,7 @@ meta_plugin_begin_modal (MetaPlugin *plugin,
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_begin_modal_for_plugin (priv->screen, plugin,
return meta_begin_modal_for_plugin (priv->compositor, plugin,
options, timestamp);
}
@ -198,7 +197,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
meta_end_modal_for_plugin (priv->compositor, plugin, timestamp);
}
/**
@ -214,16 +213,15 @@ meta_plugin_get_screen (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->screen;
return priv->compositor->display->screen;
}
void
_meta_plugin_set_screen (MetaPlugin *plugin,
MetaScreen *screen)
_meta_plugin_set_compositor (MetaPlugin *plugin, MetaCompositor *compositor)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
priv->screen = screen;
priv->compositor = compositor;
}
void

View File

@ -80,26 +80,6 @@ meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
{
MetaShapedTexture *stex = meta_surface_actor_get_texture (actor);
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
switch (cogl_texture_get_components (texture))
{
case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE;
case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH:
return FALSE;
default:
g_assert_not_reached ();
}
}
static gboolean
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
{
@ -136,14 +116,24 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
return priv->surface->window;
}
static void
meta_surface_actor_wayland_dispose (GObject *object)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object);
meta_surface_actor_wayland_set_buffer (self, NULL);
G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object);
}
static void
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
{
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
GObjectClass *object_class = G_OBJECT_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;
@ -151,6 +141,8 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
object_class->dispose = meta_surface_actor_wayland_dispose;
}
static void

View File

@ -28,7 +28,6 @@
#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>
@ -54,7 +53,6 @@ struct _MetaSurfaceActorX11Private
guint does_full_damage : 1;
/* Other state... */
guint argb32 : 1;
guint received_damage : 1;
guint size_changed : 1;
@ -266,28 +264,6 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
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)
{
@ -312,7 +288,7 @@ meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
if (window->shape_region != NULL)
return FALSE;
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
if (meta_surface_actor_is_argb32 (actor) && !meta_window_requested_bypass_compositor (window))
return FALSE;
if (!meta_window_is_monitor_sized (window))
@ -405,7 +381,6 @@ meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
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;
@ -461,8 +436,6 @@ meta_surface_actor_x11_new (MetaWindow *window)
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);

View File

@ -263,7 +263,26 @@ meta_surface_actor_pre_paint (MetaSurfaceActor *self)
gboolean
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
{
return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (self);
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
/* If we don't have a texture, like during initialization, assume
* that we're ARGB32. */
if (!texture)
return TRUE;
switch (cogl_texture_get_components (texture))
{
case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE;
case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH:
return FALSE;
default:
g_assert_not_reached ();
}
}
gboolean

View File

@ -29,7 +29,6 @@ struct _MetaSurfaceActorClass
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);

View File

@ -27,7 +27,7 @@
#include "meta-window-actor-private.h"
#include "meta-texture-rectangle.h"
#include "region-utils.h"
#include "monitor-private.h"
#include "meta-monitor-manager.h"
#include "meta-cullable.h"
#include "meta-surface-actor.h"
@ -37,8 +37,8 @@
struct _MetaWindowActorPrivate
{
MetaWindow *window;
MetaScreen *screen;
MetaWindow *window;
MetaCompositor *compositor;
MetaSurfaceActor *surface;
@ -371,11 +371,11 @@ meta_window_actor_update_surface (MetaWindowActor *self)
static void
meta_window_actor_constructed (GObject *object)
{
MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
priv->screen = window->screen;
priv->compositor = window->display->compositor;
meta_window_actor_update_surface (self);
@ -389,19 +389,15 @@ meta_window_actor_constructed (GObject *object)
static void
meta_window_actor_dispose (GObject *object)
{
MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen;
MetaCompScreen *info;
MetaCompositor *compositor = priv->compositor;
if (priv->disposed)
return;
priv->disposed = TRUE;
screen = priv->screen;
info = meta_screen_get_compositor_data (screen);
if (priv->send_frame_messages_timer != 0)
{
g_source_remove (priv->send_frame_messages_timer);
@ -416,7 +412,7 @@ meta_window_actor_dispose (GObject *object)
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
info->windows = g_list_remove (info->windows, (gconstpointer) self);
compositor->windows = g_list_remove (compositor->windows, (gconstpointer) self);
g_clear_object (&priv->window);
@ -706,7 +702,6 @@ static gboolean
meta_window_actor_has_shadow (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindowType window_type = meta_window_get_window_type (priv->window);
if (priv->no_shadow)
return FALSE;
@ -745,25 +740,6 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
if (priv->window->override_redirect)
return TRUE;
/*
* Don't put shadow around DND icon windows
*/
if (window_type == META_WINDOW_DND ||
window_type == META_WINDOW_DESKTOP)
return FALSE;
if (window_type == META_WINDOW_MENU
#if 0
|| window_type == META_WINDOW_DROPDOWN_MENU
#endif
)
return TRUE;
#if 0
if (window_type == META_WINDOW_TOOLTIP)
return TRUE;
#endif
return FALSE;
}
@ -851,8 +827,7 @@ static void
queue_send_frame_messages_timeout (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
MetaDisplay *display = meta_window_get_display (priv->window);
gint64 current_time = meta_compositor_monotonic_time_to_server_time (display, g_get_monotonic_time ());
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
MetaWindow *window = priv->window;
@ -964,7 +939,7 @@ start_simple_effect (MetaWindowActor *self,
gulong event)
{
MetaWindowActorPrivate *priv = self->priv;
MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
MetaCompositor *compositor = priv->compositor;
gint *counter = NULL;
gboolean use_freeze_thaw = FALSE;
@ -995,9 +970,7 @@ start_simple_effect (MetaWindowActor *self,
(*counter)++;
if (!meta_plugin_manager_event_simple (info->plugin_mgr,
self,
event))
if (!meta_plugin_manager_event_simple (compositor->plugin_mgr, self, event))
{
(*counter)--;
if (use_freeze_thaw)
@ -1118,15 +1091,11 @@ meta_window_actor_set_unredirected (MetaWindowActor *self,
void
meta_window_actor_destroy (MetaWindowActor *self)
{
MetaWindow *window;
MetaCompScreen *info;
MetaWindowActorPrivate *priv;
MetaWindowType window_type;
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
MetaCompositor *compositor = priv->compositor;
MetaWindowType window_type = meta_window_get_window_type (window);
priv = self->priv;
window = priv->window;
window_type = meta_window_get_window_type (window);
meta_window_set_compositor_private (window, NULL);
if (priv->send_frame_messages_timer != 0)
@ -1139,8 +1108,7 @@ meta_window_actor_destroy (MetaWindowActor *self)
* We remove the window from internal lookup hashes and thus any other
* unmap events etc fail
*/
info = meta_screen_get_compositor_data (priv->screen);
info->windows = g_list_remove (info->windows, (gconstpointer) self);
compositor->windows = g_list_remove (compositor->windows, (gconstpointer) self);
if (window_type == META_WINDOW_DROPDOWN_MENU ||
window_type == META_WINDOW_POPUP_MENU ||
@ -1201,18 +1169,14 @@ void
meta_window_actor_show (MetaWindowActor *self,
MetaCompEffect effect)
{
MetaWindowActorPrivate *priv;
MetaCompScreen *info;
gulong event;
priv = self->priv;
info = meta_screen_get_compositor_data (priv->screen);
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
gulong event = 0;
g_return_if_fail (!priv->visible);
self->priv->visible = TRUE;
event = 0;
switch (effect)
{
case META_COMP_EFFECT_CREATE:
@ -1229,7 +1193,7 @@ meta_window_actor_show (MetaWindowActor *self,
g_assert_not_reached();
}
if (info->switch_workspace_in_progress ||
if (compositor->switch_workspace_in_progress ||
event == 0 ||
!start_simple_effect (self, event))
{
@ -1241,12 +1205,9 @@ void
meta_window_actor_hide (MetaWindowActor *self,
MetaCompEffect effect)
{
MetaWindowActorPrivate *priv;
MetaCompScreen *info;
gulong event;
priv = self->priv;
info = meta_screen_get_compositor_data (priv->screen);
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
gulong event = 0;
g_return_if_fail (priv->visible);
@ -1256,10 +1217,9 @@ meta_window_actor_hide (MetaWindowActor *self,
* hold off on hiding the window, and do it after the workspace
* switch completes
*/
if (info->switch_workspace_in_progress)
if (compositor->switch_workspace_in_progress)
return;
event = 0;
switch (effect)
{
case META_COMP_EFFECT_DESTROY:
@ -1285,7 +1245,8 @@ meta_window_actor_maximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
/* The window has already been resized (in order to compute new_rect),
* which by side effect caused the actor to be resized. Restore it to the
@ -1296,7 +1257,7 @@ meta_window_actor_maximize (MetaWindowActor *self,
self->priv->maximize_in_progress++;
meta_window_actor_freeze (self);
if (!meta_plugin_manager_event_maximize (info->plugin_mgr,
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
self,
META_PLUGIN_MAXIMIZE,
new_rect->x, new_rect->y,
@ -1313,7 +1274,8 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
MetaWindowActorPrivate *priv = self->priv;
MetaCompositor *compositor = priv->compositor;
/* The window has already been resized (in order to compute new_rect),
* which by side effect caused the actor to be resized. Restore it to the
@ -1324,7 +1286,7 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
self->priv->unmaximize_in_progress++;
meta_window_actor_freeze (self);
if (!meta_plugin_manager_event_maximize (info->plugin_mgr,
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
self,
META_PLUGIN_UNMAXIMIZE,
new_rect->x, new_rect->y,
@ -1338,8 +1300,8 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
MetaWindowActor *
meta_window_actor_new (MetaWindow *window)
{
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_window_get_display (window);
MetaCompositor *compositor = display->compositor;
MetaWindowActor *self;
MetaWindowActorPrivate *priv;
ClutterActor *window_group;
@ -1364,9 +1326,9 @@ meta_window_actor_new (MetaWindow *window)
meta_window_set_compositor_private (window, G_OBJECT (self));
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
window_group = info->top_window_group;
window_group = compositor->top_window_group;
else
window_group = info->window_group;
window_group = compositor->window_group;
clutter_actor_add_child (window_group, CLUTTER_ACTOR (self));
@ -1375,7 +1337,7 @@ meta_window_actor_new (MetaWindow *window)
/* Initial position in the stack is arbitrary; stacking will be synced
* before we first paint.
*/
info->windows = g_list_append (info->windows, self);
compositor->windows = g_list_append (compositor->windows, self);
return self;
}
@ -1756,41 +1718,20 @@ static void
meta_window_actor_update_input_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *region = NULL;
cairo_rectangle_int_t client_area;
MetaWindow *window = priv->window;
cairo_region_t *region;
meta_window_get_client_area_rect (priv->window, &client_area);
if (priv->window->frame != NULL)
if (window->shape_region && window->input_region)
{
region = meta_frame_get_frame_bounds (priv->window->frame);
/* input_region is in client window coordinates, so translate the
* input region into that coordinate system and back */
cairo_region_translate (region, -client_area.x, -client_area.y);
cairo_region_union_rectangle (region, &client_area);
cairo_region_translate (region, client_area.x, client_area.y);
}
else if (priv->window->shape_region != NULL ||
priv->window->input_region != NULL)
{
if (priv->window->shape_region != NULL)
{
region = cairo_region_copy (priv->window->shape_region);
if (priv->window->input_region != NULL)
cairo_region_intersect (region, priv->window->input_region);
}
else
region = cairo_region_reference (priv->window->input_region);
region = cairo_region_copy (window->shape_region);
cairo_region_intersect (region, window->input_region);
}
else if (window->shape_region)
region = cairo_region_reference (window->shape_region);
else if (window->input_region)
region = cairo_region_reference (window->input_region);
else
{
/* If we don't have a shape on the server, that means that
* we have an implicit shape of one rectangle covering the
* entire window. */
region = cairo_region_create_rectangle (&client_area);
}
region = NULL;
meta_surface_actor_set_input_region (priv->surface, region);
cairo_region_destroy (region);
@ -1912,8 +1853,7 @@ static void
do_send_frame_drawn (MetaWindowActor *self, FrameData *frame)
{
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
MetaDisplay *display = meta_window_get_display (priv->window);
Display *xdisplay = meta_display_get_xdisplay (display);
XClientMessageEvent ev = { 0, };
@ -1965,7 +1905,7 @@ do_send_frame_timings (MetaWindowActor *self,
gint64 presentation_time)
{
MetaWindowActorPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
MetaDisplay *display = meta_window_get_display (priv->window);
Display *xdisplay = meta_display_get_xdisplay (display);
XClientMessageEvent ev = { 0, };

View File

@ -74,26 +74,8 @@ static void
bell_flash_fullscreen (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
{
XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev;
MetaScreen *screen;
g_assert (xkb_ev->xkb_type == XkbBellNotify);
if (xkb_bell_ev->window != None)
{
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
if (screen)
meta_compositor_flash_screen (display->compositor, screen);
}
else
{
GSList *screen_list = display->screens;
while (screen_list)
{
screen = (MetaScreen *) screen_list->data;
meta_compositor_flash_screen (display->compositor, screen);
screen_list = screen_list->next;
}
}
meta_compositor_flash_screen (display->compositor, display->screen);
}
/**

View File

@ -274,7 +274,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
MetaStackWindow stack_sibling;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, xwindow);
screen = display->screen;
grab_window = display->grab_window;
if (grab_window == NULL)
@ -603,13 +603,10 @@ meta_core_get_workspace_name_with_index (Display *xdisplay,
int index)
{
MetaDisplay *display;
MetaScreen *screen;
MetaWorkspace *workspace;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_root (display, xroot);
g_assert (screen != NULL);
workspace = meta_screen_get_workspace_by_index (screen, index);
workspace = meta_screen_get_workspace_by_index (display->screen, index);
return workspace ? meta_workspace_get_name (workspace) : NULL;
}
@ -630,7 +627,7 @@ meta_core_begin_grab_op (Display *xdisplay,
MetaScreen *screen;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, frame_xwindow);
screen = display->screen;
g_assert (screen != NULL);
@ -670,10 +667,6 @@ meta_core_get_grab_frame (Display *xdisplay)
display = meta_display_for_x_display (xdisplay);
g_assert (display != NULL);
g_assert (display->grab_op == META_GRAB_OP_NONE ||
display->grab_screen != NULL);
g_assert (display->grab_op == META_GRAB_OP_NONE ||
display->grab_screen->display->xdisplay == xdisplay);
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window &&

View File

@ -31,6 +31,7 @@
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
#include <meta/common.h>
#include <meta/boxes.h>
#include <meta/display.h>
@ -148,8 +149,7 @@ struct _MetaDisplay
/*< private-ish >*/
guint error_trap_synced_at_last_pop : 1;
GSList *screens;
MetaScreen *active_screen;
MetaScreen *screen;
GHashTable *xids;
GHashTable *wayland_windows;
int error_traps;
@ -190,7 +190,6 @@ struct _MetaDisplay
/* current window operation */
MetaGrabOp grab_op;
MetaScreen *grab_screen;
MetaWindow *grab_window;
Window grab_xwindow;
int grab_button;
@ -351,10 +350,6 @@ struct _MetaDisplayClass
gboolean meta_display_open (void);
void meta_display_close (MetaDisplay *display,
guint32 timestamp);
MetaScreen* meta_display_screen_for_x_screen (MetaDisplay *display,
Screen *screen);
MetaScreen* meta_display_screen_for_xwindow (MetaDisplay *display,
Window xindow);
void meta_display_grab (MetaDisplay *display);
void meta_display_ungrab (MetaDisplay *display);
@ -403,6 +398,8 @@ MetaDisplay* meta_get_display (void);
Cursor meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor);
XcursorImage *meta_display_load_x_cursor (MetaDisplay *display,
MetaCursor cursor);
void meta_display_set_grab_op_cursor (MetaDisplay *display,
MetaScreen *screen,

View File

@ -48,7 +48,7 @@
#include <meta/compositor-mutter.h>
#include <X11/Xatom.h>
#include "mutter-enum-types.h"
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "meta-cursor-tracker-private.h"
#ifdef HAVE_RANDR
@ -362,8 +362,6 @@ sn_error_trap_pop (SnDisplay *sn_display,
static void
enable_compositor (MetaDisplay *display)
{
GSList *list;
if (!META_DISPLAY_HAS_COMPOSITE (display) ||
!META_DISPLAY_HAS_DAMAGE (display) ||
!META_DISPLAY_HAS_RENDER (display))
@ -379,14 +377,8 @@ enable_compositor (MetaDisplay *display)
if (!display->compositor)
return;
for (list = display->screens; list != NULL; list = list->next)
{
MetaScreen *screen = list->data;
meta_compositor_manage_screen (screen->display->compositor,
screen);
}
meta_compositor_manage (display->compositor);
}
static void
@ -440,7 +432,6 @@ gboolean
meta_display_open (void)
{
Display *xdisplay;
GSList *screens;
MetaScreen *screen;
int i;
guint32 timestamp;
@ -536,8 +527,7 @@ meta_display_open (void)
the_display->window_with_menu = NULL;
the_display->window_menu = NULL;
the_display->screens = NULL;
the_display->active_screen = NULL;
the_display->screen = NULL;
#ifdef HAVE_STARTUP_NOTIFICATION
the_display->sn_display = sn_display_new (the_display->xdisplay,
@ -572,7 +562,6 @@ meta_display_open (void)
the_display->grab_op = META_GRAB_OP_NONE;
the_display->grab_window = NULL;
the_display->grab_screen = NULL;
the_display->grab_resize_popup = NULL;
the_display->grab_tile_mode = META_TILE_NONE;
the_display->grab_tile_monitor_number = -1;
@ -841,15 +830,12 @@ meta_display_open (void)
the_display->last_focus_time = timestamp;
the_display->last_user_time = timestamp;
the_display->compositor = NULL;
/* Mutter used to manage all X screens of the display in a single process, but
* now it always manages exactly one screen as specified by the DISPLAY
* environment variable. The screens GSList is left for simplicity.
* environment variable.
*/
screens = NULL;
i = meta_ui_get_screen_number ();
screen = meta_screen_new (the_display, i, timestamp);
if (!screen)
@ -861,9 +847,7 @@ meta_display_open (void)
return FALSE;
}
screens = g_slist_prepend (screens, screen);
the_display->screens = screens;
the_display->screen = screen;
enable_compositor (the_display);
@ -895,7 +879,7 @@ meta_display_open (void)
if (focus == None || focus == PointerRoot)
/* Just focus the no_focus_window on the first screen */
meta_display_focus_the_no_focus_window (the_display,
the_display->screens->data,
the_display->screen,
timestamp);
else
{
@ -906,7 +890,7 @@ meta_display_open (void)
else
/* Just focus the no_focus_window on the first screen */
meta_display_focus_the_no_focus_window (the_display,
the_display->screens->data,
the_display->screen,
timestamp);
}
@ -948,8 +932,8 @@ meta_display_list_windows (MetaDisplay *display,
MetaListWindowsFlags flags)
{
GSList *winlist;
GSList *tmp;
GSList *prev;
GSList *tmp;
GHashTableIter iter;
gpointer key, value;
@ -1024,8 +1008,6 @@ void
meta_display_close (MetaDisplay *display,
guint32 timestamp)
{
GSList *tmp;
g_assert (display != NULL);
if (display->closing != 0)
@ -1053,17 +1035,7 @@ meta_display_close (MetaDisplay *display,
/* Stop caring about events */
meta_display_free_events (display);
/* Free all screens */
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_free (screen, timestamp);
tmp = tmp->next;
}
g_slist_free (display->screens);
display->screens = NULL;
meta_screen_free (display->screen, timestamp);
#ifdef HAVE_STARTUP_NOTIFICATION
if (display->sn_display)
@ -1099,77 +1071,6 @@ meta_display_close (MetaDisplay *display,
meta_quit (META_EXIT_SUCCESS);
}
/**
* meta_display_screen_for_root:
* @display: a #MetaDisplay
* @xroot: a X window
*
* Return the #MetaScreen corresponding to a specified X root window ID.
*
* Return Value: (transfer none): the screen for the specified root window ID, or %NULL
*/
MetaScreen*
meta_display_screen_for_root (MetaDisplay *display,
Window xroot)
{
GSList *tmp;
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
if (xroot == screen->xroot)
return screen;
tmp = tmp->next;
}
return NULL;
}
MetaScreen*
meta_display_screen_for_xwindow (MetaDisplay *display,
Window xwindow)
{
XWindowAttributes attr;
int result;
meta_error_trap_push (display);
attr.screen = NULL;
result = XGetWindowAttributes (display->xdisplay, xwindow, &attr);
meta_error_trap_pop (display);
/* Note, XGetWindowAttributes is on all kinds of crack
* and returns 1 on success 0 on failure, rather than Success
* on success.
*/
if (result == 0 || attr.screen == NULL)
return NULL;
return meta_display_screen_for_x_screen (display, attr.screen);
}
MetaScreen*
meta_display_screen_for_x_screen (MetaDisplay *display,
Screen *xscreen)
{
GSList *tmp;
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
if (xscreen == screen->xscreen)
return screen;
tmp = tmp->next;
}
return NULL;
}
/* Grab/ungrab routines taken from fvwm.
* Calling this function will cause X to ignore all other clients until
* you ungrab. This may not be quite as bad as it sounds, yet there is
@ -1775,7 +1676,6 @@ request_xserver_input_focus_change (MetaDisplay *display,
meta_error_trap_pop (display);
display->last_focus_time = timestamp;
display->active_screen = screen;
if (meta_window == NULL || meta_window != display->autoraise_window)
meta_display_remove_autoraise_callback (display);
@ -1877,18 +1777,7 @@ gboolean
meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
Window xwindow)
{
gboolean is_a_no_focus_window = FALSE;
GSList *temp = display->screens;
while (temp != NULL) {
MetaScreen *screen = temp->data;
if (screen->no_focus_window == xwindow) {
is_a_no_focus_window = TRUE;
break;
}
temp = temp->next;
}
return is_a_no_focus_window;
return xwindow == display->screen->no_focus_window;
}
static MetaCursor
@ -1950,6 +1839,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
MetaCursor cursor = meta_cursor_for_grab_op (op);
MetaCursorReference *cursor_ref;
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
@ -1983,7 +1873,9 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
meta_error_trap_pop (display);
meta_cursor_tracker_set_grab_cursor (screen->cursor_tracker, cursor);
cursor_ref = meta_cursor_tracker_get_cursor_from_theme (screen->cursor_tracker, cursor);
meta_cursor_tracker_set_grab_cursor (screen->cursor_tracker, cursor_ref);
meta_cursor_reference_unref (cursor_ref);
}
gboolean
@ -2087,7 +1979,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_op = op;
display->grab_window = grab_window;
display->grab_screen = screen;
display->grab_xwindow = grab_xwindow;
display->grab_button = button;
display->grab_mask = modmask;
@ -2140,7 +2031,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
"Grab op %u on window %s successful\n",
display->grab_op, window ? window->desc : "(null)");
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
g_assert (display->grab_window != NULL);
g_assert (display->grab_op != META_GRAB_OP_NONE);
if (display->grab_window)
@ -2168,7 +2059,7 @@ meta_display_end_grab_op (MetaDisplay *display,
return;
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->grab_screen, display->grab_window, display->grab_op);
display->screen, display->grab_window, display->grab_op);
if (display->grab_window != NULL)
display->grab_window->shaken_loose = FALSE;
@ -2220,14 +2111,13 @@ meta_display_end_grab_op (MetaDisplay *display,
if (display->grab_window)
meta_window_ungrab_all_keys (display->grab_window, timestamp);
else
meta_screen_ungrab_all_keys (display->grab_screen, timestamp);
meta_screen_ungrab_all_keys (display->screen, timestamp);
}
meta_cursor_tracker_set_grab_cursor (display->grab_screen->cursor_tracker, META_CURSOR_DEFAULT);
meta_cursor_tracker_set_grab_cursor (display->screen->cursor_tracker, NULL);
display->grab_timestamp = 0;
display->grab_window = NULL;
display->grab_screen = NULL;
display->grab_xwindow = None;
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
@ -2517,30 +2407,19 @@ meta_display_increment_event_serial (MetaDisplay *display)
void
meta_display_update_active_window_hint (MetaDisplay *display)
{
GSList *tmp;
gulong data[1];
if (display->focus_window)
data[0] = display->focus_window->xwindow;
else
data[0] = None;
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_error_trap_push (display);
XChangeProperty (display->xdisplay, screen->xroot,
display->atom__NET_ACTIVE_WINDOW,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (display);
tmp = tmp->next;
}
meta_error_trap_push (display);
XChangeProperty (display->xdisplay, display->screen->xroot,
display->atom__NET_ACTIVE_WINDOW,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (display);
}
void
@ -2578,22 +2457,12 @@ void
meta_display_set_cursor_theme (const char *theme,
int size)
{
GSList *tmp;
MetaDisplay *display = meta_get_display ();
XcursorSetTheme (display->xdisplay, theme);
XcursorSetDefaultSize (display->xdisplay, size);
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_update_cursor (screen);
tmp = tmp->next;
}
meta_screen_update_cursor (display->screen);
}
/*
@ -2808,7 +2677,6 @@ get_focused_group (MetaDisplay *display)
static MetaWindow*
find_tab_forward (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
GList *start,
gboolean skip_first)
@ -2826,8 +2694,7 @@ find_tab_forward (MetaDisplay *display,
{
MetaWindow *window = tmp->data;
if (window->screen == screen &&
IN_TAB_CHAIN (window, type))
if (IN_TAB_CHAIN (window, type))
return window;
tmp = tmp->next;
@ -2850,7 +2717,6 @@ find_tab_forward (MetaDisplay *display,
static MetaWindow*
find_tab_backward (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
GList *start,
gboolean skip_last)
@ -2867,8 +2733,7 @@ find_tab_backward (MetaDisplay *display,
{
MetaWindow *window = tmp->data;
if (window->screen == screen &&
IN_TAB_CHAIN (window, type))
if (IN_TAB_CHAIN (window, type))
return window;
tmp = tmp->prev;
@ -2948,8 +2813,7 @@ meta_display_get_tab_list (MetaDisplay *display,
{
MetaWindow *window = tmp->data;
if (window->screen == screen &&
IN_TAB_CHAIN (window, type))
if (IN_TAB_CHAIN (window, type))
tab_list = g_list_prepend (tab_list, window);
}
@ -2979,7 +2843,6 @@ meta_display_get_tab_list (MetaDisplay *display,
* meta_display_get_tab_next:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: origin workspace
* @window: (allow-none): starting window
* @backward: If %TRUE, look for the previous window.
@ -2993,7 +2856,6 @@ meta_display_get_tab_list (MetaDisplay *display,
MetaWindow*
meta_display_get_tab_next (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
MetaWindow *window,
gboolean backward)
@ -3001,10 +2863,7 @@ meta_display_get_tab_next (MetaDisplay *display,
gboolean skip;
GList *tab_list;
MetaWindow *ret;
tab_list = meta_display_get_tab_list(display,
type,
screen,
workspace);
tab_list = meta_display_get_tab_list (display, type, NULL, workspace);
if (tab_list == NULL)
return NULL;
@ -3014,26 +2873,18 @@ meta_display_get_tab_next (MetaDisplay *display,
g_assert (window->display == display);
if (backward)
ret = find_tab_backward (display, type, screen, workspace,
g_list_find (tab_list,
window),
TRUE);
ret = find_tab_backward (display, type, workspace, g_list_find (tab_list, window), TRUE);
else
ret = find_tab_forward (display, type, screen, workspace,
g_list_find (tab_list,
window),
TRUE);
ret = find_tab_forward (display, type, workspace, g_list_find (tab_list, window), TRUE);
}
else
{
skip = display->focus_window != NULL &&
tab_list->data == display->focus_window;
if (backward)
ret = find_tab_backward (display, type, screen, workspace,
tab_list, skip);
ret = find_tab_backward (display, type, workspace, tab_list, skip);
else
ret = find_tab_forward (display, type, screen, workspace,
tab_list, skip);
ret = find_tab_forward (display, type, workspace, tab_list, skip);
}
g_list_free (tab_list);
@ -3044,7 +2895,6 @@ meta_display_get_tab_next (MetaDisplay *display,
* meta_display_get_tab_current:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: origin workspace
*
* Determine the active window that should be displayed for Alt-TAB.
@ -3055,7 +2905,6 @@ meta_display_get_tab_next (MetaDisplay *display,
MetaWindow*
meta_display_get_tab_current (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace)
{
MetaWindow *window;
@ -3063,7 +2912,6 @@ meta_display_get_tab_current (MetaDisplay *display,
window = display->focus_window;
if (window != NULL &&
window->screen == screen &&
IN_TAB_CHAIN (window, type) &&
(workspace == NULL ||
meta_window_located_on_workspace (window, workspace)))
@ -3129,14 +2977,7 @@ meta_display_unmanage_screen (MetaDisplay *display,
{
meta_verbose ("Unmanaging screen %d on display %s\n",
screen->number, display->name);
g_return_if_fail (g_slist_find (display->screens, screen) != NULL);
meta_screen_free (screen, timestamp);
display->screens = g_slist_remove (display->screens, screen);
if (display->screens == NULL)
meta_display_close (display, timestamp);
meta_display_close (display, timestamp);
}
void
@ -3178,15 +3019,7 @@ meta_display_stack_cmp (const void *a,
MetaWindow *aw = (void*) a;
MetaWindow *bw = (void*) b;
if (aw->screen == bw->screen)
return meta_stack_windows_cmp (aw->screen->stack, aw, bw);
/* Then assume screens are stacked by number */
else if (aw->screen->number < bw->screen->number)
return -1;
else if (aw->screen->number > bw->screen->number)
return 1;
else
return 0; /* not reached in theory, if windows on same display */
return meta_stack_windows_cmp (aw->screen->stack, aw, bw);
}
/**
@ -3322,7 +3155,7 @@ meta_display_increment_focus_sentinel (MetaDisplay *display)
data[0] = meta_display_get_current_time (display);
XChangeProperty (display->xdisplay,
((MetaScreen*) display->screens->data)->xroot,
display->screen->xroot,
display->atom__MUTTER_SENTINEL,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
@ -3526,18 +3359,6 @@ meta_display_get_compositor (MetaDisplay *display)
return display->compositor;
}
/**
* meta_display_get_screens:
* @display: a #MetaDisplay
*
* Returns: (transfer none) (element-type Meta.Screen): Screens for this display
*/
GSList *
meta_display_get_screens (MetaDisplay *display)
{
return display->screens;
}
gboolean
meta_display_has_shape (MetaDisplay *display)
{

View File

@ -30,7 +30,6 @@
*/
#define WINDOW_EDGES_RELEVANT(window, display) \
meta_window_should_be_showing (window) && \
window->screen == display->grab_screen && \
window != display->grab_window && \
window->type != META_WINDOW_DESKTOP && \
window->type != META_WINDOW_MENU && \
@ -963,9 +962,9 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
/*
* 1st: Get the list of relevant windows, from bottom to top
*/
stacked_windows =
meta_stack_list_windows (display->grab_screen->stack,
display->grab_screen->active_workspace);
stacked_windows =
meta_stack_list_windows (display->screen->stack,
display->screen->active_workspace);
/*
* 2nd: we need to separate that stacked list into a list of windows that
@ -1026,7 +1025,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
* by other windows or DOCKS, but that's handled below).
*/
meta_rectangle_intersect (&cur_rect,
&display->grab_screen->rect,
&display->screen->rect,
&reduced);
new_edges = NULL;
@ -1123,8 +1122,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
*/
cache_edges (display,
edges,
display->grab_screen->active_workspace->monitor_edges,
display->grab_screen->active_workspace->screen_edges);
display->screen->active_workspace->monitor_edges,
display->screen->active_workspace->screen_edges);
g_list_free (edges);
/*

View File

@ -34,7 +34,8 @@
#include "window-private.h"
#include "bell.h"
#include "workspace-private.h"
#include "meta-idle-monitor-private.h"
#include "backends/x11/meta-idle-monitor-xsync.h"
#include "backends/native/meta-idle-monitor-native.h"
#include "x11/window-x11.h"
#include "x11/xprops.h"
@ -666,10 +667,10 @@ G_GNUC_UNUSED static void
meta_spew_event (MetaDisplay *display,
XEvent *event)
{
MetaScreen *screen = display->screen;
const char *name = NULL;
char *extra = NULL;
char *winname;
MetaScreen *screen;
XIEvent *input_event;
/* filter overnumerous events */
@ -693,9 +694,7 @@ meta_spew_event (MetaDisplay *display,
else
meta_spew_core_event (display, event, &name, &extra);
screen = meta_display_screen_for_root (display, event->xany.window);
if (screen)
if (event->xany.window == screen->xroot)
winname = g_strdup_printf ("root %d", screen->number);
else
winname = g_strdup_printf ("0x%lx", event->xany.window);
@ -735,7 +734,7 @@ handle_window_focus_event (MetaDisplay *display,
}
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
window_type = "no_focus_window";
else if (meta_display_screen_for_root (display, event->event))
else if (event->event == display->screen->xroot)
window_type = "root window";
else
window_type = "unknown window";
@ -855,7 +854,7 @@ handle_input_xevent (MetaDisplay *display,
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
Window modified;
MetaWindow *window;
MetaScreen *screen;
MetaScreen *screen = display->screen;
if (input_event == NULL)
return FALSE;
@ -869,20 +868,6 @@ handle_input_xevent (MetaDisplay *display,
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
/* If the mouse switches screens, active the default window on the new
* screen; this will make keybindings and workspace-launched items
* actually appear on the right screen.
*/
{
MetaScreen *new_screen =
meta_display_screen_for_root (display, enter_event->root);
if (new_screen != NULL && display->active_screen != new_screen)
meta_workspace_focus_default_window (new_screen->active_workspace,
NULL,
enter_event->time);
}
/* Check if we've entered a window; do this even if window->has_focus to
* avoid races.
*/
@ -923,8 +908,6 @@ handle_input_xevent (MetaDisplay *display,
if (enter_event->root != enter_event->event)
break;
screen = meta_display_screen_for_root (display, enter_event->root);
if (enter_event->evtype == XI_FocusIn &&
enter_event->mode == XINotifyDetailNone)
{
@ -1013,21 +996,9 @@ process_request_frame_extents (MetaDisplay *display,
if ((hints_set && hints->decorations) || !hints_set)
{
MetaFrameBorders borders;
MetaScreen *screen;
screen = meta_display_screen_for_xwindow (display,
event->xclient.window);
if (screen == NULL)
{
meta_warning ("Received request to set _NET_FRAME_EXTENTS "
"on 0x%lx which is on a screen we are not managing\n",
event->xclient.window);
meta_XFree (hints);
return;
}
/* Return estimated frame extents for a normal window. */
meta_ui_theme_get_frame_borders (screen->ui,
meta_ui_theme_get_frame_borders (display->screen->ui,
META_FRAME_TYPE_NORMAL,
0,
&borders);
@ -1052,28 +1023,6 @@ process_request_frame_extents (MetaDisplay *display,
meta_XFree (hints);
}
static MetaScreen*
find_screen_for_selection (MetaDisplay *display,
Window owner,
Atom selection)
{
GSList *tmp;
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
if (screen->wm_sn_selection_window == owner &&
screen->wm_sn_atom == selection)
return screen;
tmp = tmp->next;
}
return NULL;
}
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
static gboolean
convert_property (MetaDisplay *display,
@ -1128,14 +1077,11 @@ static void
process_selection_request (MetaDisplay *display,
XEvent *event)
{
MetaScreen *screen = display->screen;
XSelectionEvent reply;
MetaScreen *screen;
screen = find_screen_for_selection (display,
event->xselectionrequest.owner,
event->xselectionrequest.selection);
if (screen == NULL)
if (screen->wm_sn_selection_window != event->xselectionrequest.owner ||
screen->wm_sn_atom != event->xselectionrequest.selection)
{
char *str;
@ -1231,41 +1177,31 @@ static void
process_selection_clear (MetaDisplay *display,
XEvent *event)
{
/* We need to unmanage the screen on which we lost the selection */
MetaScreen *screen;
MetaScreen *screen = display->screen;
screen = find_screen_for_selection (display,
event->xselectionclear.window,
event->xselectionclear.selection);
if (screen != NULL)
if (screen->wm_sn_selection_window != event->xselectionclear.window ||
screen->wm_sn_atom != event->xselectionclear.selection)
{
meta_verbose ("Got selection clear for screen %d on display %s\n",
screen->number, display->name);
char *str;
meta_display_unmanage_screen (display,
screen,
event->xselectionclear.time);
meta_error_trap_push (display);
str = XGetAtomName (display->xdisplay,
event->xselectionclear.selection);
meta_error_trap_pop (display);
/* display and screen may both be invalid memory... */
meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
str ? str : "(bad atom)", event->xselectionclear.window);
meta_XFree (str);
return;
}
{
char *str;
meta_verbose ("Got selection clear for screen %d on display %s\n",
screen->number, display->name);
meta_error_trap_push (display);
str = XGetAtomName (display->xdisplay,
event->xselectionclear.selection);
meta_error_trap_pop (display);
meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
str ? str : "(bad atom)", event->xselectionclear.window);
meta_XFree (str);
}
meta_display_unmanage_screen (display, display->screen,
event->xselectionclear.time);
}
static gboolean
@ -1309,7 +1245,7 @@ handle_other_xevent (MetaDisplay *display,
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
}
else
meta_idle_monitor_handle_xevent_all (event);
meta_idle_monitor_xsync_handle_xevent_all (event);
goto out;
}
@ -1356,24 +1292,16 @@ handle_other_xevent (MetaDisplay *display,
break;
case CreateNotify:
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xcreatewindow.parent);
if (screen)
meta_stack_tracker_create_event (screen->stack_tracker,
if (event->xcreatewindow.parent == display->screen->xroot)
meta_stack_tracker_create_event (display->screen->stack_tracker,
&event->xcreatewindow);
}
break;
case DestroyNotify:
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xdestroywindow.event);
if (screen)
meta_stack_tracker_destroy_event (screen->stack_tracker,
if (event->xdestroywindow.event == display->screen->xroot)
meta_stack_tracker_destroy_event (display->screen->stack_tracker,
&event->xdestroywindow);
}
if (window)
@ -1447,8 +1375,7 @@ handle_other_xevent (MetaDisplay *display,
/* NB: override redirect windows wont cause a map request so we
* watch out for map notifies against any root windows too if a
* compositor is enabled: */
if (window == NULL
&& meta_display_screen_for_root (display, event->xmap.event))
if (window == NULL && event->xmap.event == display->screen->xroot)
{
window = meta_window_x11_new (display, event->xmap.window,
FALSE, META_COMP_EFFECT_CREATE);
@ -1480,24 +1407,16 @@ handle_other_xevent (MetaDisplay *display,
break;
case ReparentNotify:
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xconfigure.event);
if (screen)
meta_stack_tracker_reparent_event (screen->stack_tracker,
if (event->xreparent.event == display->screen->xroot)
meta_stack_tracker_reparent_event (display->screen->stack_tracker,
&event->xreparent);
}
break;
case ConfigureNotify:
if (event->xconfigure.event != event->xconfigure.window)
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xconfigure.event);
if (screen)
meta_stack_tracker_configure_event (screen->stack_tracker,
if (event->xconfigure.event == display->screen->xroot)
meta_stack_tracker_configure_event (display->screen->stack_tracker,
&event->xconfigure);
}
@ -1551,7 +1470,6 @@ handle_other_xevent (MetaDisplay *display,
case PropertyNotify:
{
MetaGroup *group;
MetaScreen *screen;
if (window && !frame_was_receiver)
meta_window_x11_property_notify (window, event);
@ -1563,24 +1481,18 @@ handle_other_xevent (MetaDisplay *display,
if (group != NULL)
meta_group_property_notify (group, event);
screen = NULL;
if (window == NULL &&
group == NULL) /* window/group != NULL means it wasn't a root window */
screen = meta_display_screen_for_root (display,
event->xproperty.window);
if (screen != NULL)
if (event->xproperty.window == display->screen->xroot)
{
if (event->xproperty.atom ==
display->atom__NET_DESKTOP_LAYOUT)
meta_screen_update_workspace_layout (screen);
meta_screen_update_workspace_layout (display->screen);
else if (event->xproperty.atom ==
display->atom__NET_DESKTOP_NAMES)
meta_screen_update_workspace_names (screen);
meta_screen_update_workspace_names (display->screen);
else if (meta_is_wayland_compositor () &&
event->xproperty.atom ==
display->atom__XKB_RULES_NAMES)
reload_xkb_rules (screen);
reload_xkb_rules (display->screen);
#if 0
else if (event->xproperty.atom ==
display->atom__NET_RESTACK_WINDOW)
@ -1629,12 +1541,7 @@ handle_other_xevent (MetaDisplay *display,
}
else
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xclient.window);
if (screen)
if (event->xclient.window == display->screen->xroot)
{
if (event->xclient.message_type ==
display->atom__NET_CURRENT_DESKTOP)
@ -1650,9 +1557,7 @@ handle_other_xevent (MetaDisplay *display,
"specified timestamp of %u\n",
space, time);
workspace =
meta_screen_get_workspace_by_index (screen,
space);
workspace = meta_screen_get_workspace_by_index (display->screen, space);
/* Handle clients using the older version of the spec... */
if (time == 0 && workspace)
@ -1693,11 +1598,11 @@ handle_other_xevent (MetaDisplay *display,
showing_desktop ? "show" : "hide");
if (showing_desktop)
meta_screen_show_desktop (screen, timestamp);
meta_screen_show_desktop (display->screen, timestamp);
else
{
meta_screen_unshow_desktop (screen);
meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
meta_screen_unshow_desktop (display->screen);
meta_workspace_focus_default_window (display->screen->active_workspace, NULL, timestamp);
}
}
else if (event->xclient.message_type ==
@ -1837,7 +1742,6 @@ meta_display_handle_xevent (MetaDisplay *display,
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
XIEvent *input_event;
MetaMonitorManager *monitor;
MetaScreen *screen;
#if 0
meta_spew_event (display, event);
@ -1875,10 +1779,9 @@ meta_display_handle_xevent (MetaDisplay *display,
FALSE);
}
screen = meta_display_screen_for_root (display, event->xany.window);
if (screen)
if (event->xany.window == display->screen->xroot)
{
if (meta_screen_handle_xevent (screen, event))
if (meta_screen_handle_xevent (display->screen, event))
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
@ -1948,6 +1851,38 @@ meta_display_handle_xevent (MetaDisplay *display,
return bypass_gtk;
}
static void
handle_idletime_for_event (const ClutterEvent *event)
{
ClutterInputDevice *device, *source_device;
MetaIdleMonitor *core_monitor, *device_monitor;
int device_id;
/* This is handled by XSync under X11. */
if (!meta_is_wayland_compositor ())
return;
device = clutter_event_get_device (event);
if (device == NULL)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (core_monitor);
meta_idle_monitor_native_reset_idletime (device_monitor);
source_device = clutter_event_get_source_device (event);
if (source_device != device)
{
device_id = clutter_input_device_get_device_id (device);
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (device_monitor);
}
}
static gboolean
meta_display_handle_event (MetaDisplay *display,
const ClutterEvent *event)
@ -1962,6 +1897,8 @@ meta_display_handle_event (MetaDisplay *display,
meta_wayland_compositor_update (compositor, event);
}
handle_idletime_for_event (event);
window = get_window_for_event (display, event);
display->current_time = event->any.time;
@ -2222,13 +2159,17 @@ meta_display_handle_event (MetaDisplay *display,
return bypass_clutter;
}
static gboolean
xevent_callback (XEvent *event,
gpointer data)
static GdkFilterReturn
xevent_filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
MetaDisplay *display = data;
return meta_display_handle_xevent (display, event);
if (meta_display_handle_xevent (display, xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
}
static gboolean
@ -2243,9 +2184,7 @@ event_callback (const ClutterEvent *event,
void
meta_display_init_events (MetaDisplay *display)
{
meta_ui_add_event_func (display->xdisplay,
xevent_callback,
display);
gdk_window_add_filter (NULL, xevent_filter, display);
display->clutter_event_filter = clutter_event_add_filter (NULL,
event_callback,
NULL,
@ -2255,9 +2194,7 @@ meta_display_init_events (MetaDisplay *display)
void
meta_display_free_events (MetaDisplay *display)
{
meta_ui_remove_event_func (display->xdisplay,
xevent_callback,
display);
gdk_window_remove_filter (NULL, xevent_filter, display);
clutter_event_remove_filter (display->clutter_event_filter);
display->clutter_event_filter = 0;
}

View File

@ -52,6 +52,7 @@
#endif
#include "wayland/meta-wayland.h"
#include "meta-backend.h"
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
@ -685,15 +686,7 @@ ungrab_key_bindings (MetaDisplay *display)
meta_error_trap_push (display); /* for efficiency push outer trap */
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_ungrab_keys (screen);
tmp = tmp->next;
}
meta_screen_ungrab_keys (display->screen);
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
tmp = windows;
@ -718,15 +711,7 @@ grab_key_bindings (MetaDisplay *display)
meta_error_trap_push (display); /* for efficiency push outer trap */
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_grab_keys (screen);
tmp = tmp->next;
}
meta_screen_grab_keys (display->screen);
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
tmp = windows;
@ -1298,7 +1283,6 @@ meta_display_grab_accelerator (MetaDisplay *display,
guint keycode = 0;
guint mask = 0;
MetaVirtualModifier modifiers = 0;
GSList *l;
if (!meta_ui_parse_accelerator (accelerator, &keysym, &keycode, &modifiers))
{
@ -1318,11 +1302,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
if (display_get_keybinding (display, keycode, mask))
return META_KEYBINDING_ACTION_NONE;
for (l = display->screens; l; l = l->next)
{
MetaScreen *screen = l->data;
meta_change_keygrab (display, screen->xroot, TRUE, keysym, keycode, mask);
}
meta_change_keygrab (display, display->screen->xroot, TRUE, keysym, keycode, mask);
grab = g_new0 (MetaKeyGrab, 1);
grab->action = next_dynamic_keybinding_action ();
@ -1372,16 +1352,11 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
if (binding)
{
guint32 index_key;
GSList *l;
for (l = display->screens; l; l = l->next)
{
MetaScreen *screen = l->data;
meta_change_keygrab (display, screen->xroot, FALSE,
binding->keysym,
binding->keycode,
binding->mask);
}
meta_change_keygrab (display, display->screen->xroot, FALSE,
binding->keysym,
binding->keycode,
binding->mask);
index_key = key_binding_key (binding->keycode, binding->mask);
g_hash_table_remove (display->key_bindings_index, GINT_TO_POINTER (index_key));
@ -1686,7 +1661,7 @@ process_event (MetaDisplay *display,
/* If the compositor filtered out the keybindings, that
* means they don't want the binding to trigger, so we do
* the same thing as if the binding didn't exist. */
if (meta_compositor_filter_keybinding (display->compositor, screen, binding))
if (meta_compositor_filter_keybinding (display->compositor, binding))
goto not_found;
if (binding->handler == NULL)
@ -1771,7 +1746,7 @@ process_overlay_key (MetaDisplay *display,
display->overlay_key_combo.keycode,
display->grab_mask);
if (binding &&
meta_compositor_filter_keybinding (display->compositor, screen, binding))
meta_compositor_filter_keybinding (display->compositor, binding))
return TRUE;
meta_display_overlay_key_activate (display);
}
@ -1871,8 +1846,7 @@ meta_display_process_key_event (MetaDisplay *display,
/* window may be NULL */
/* XXX */
screen = display->active_screen;
screen = display->screen;
all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed;
if (!all_keys_grabbed)
@ -1899,8 +1873,7 @@ meta_display_process_key_event (MetaDisplay *display,
* we're in some special keyboard mode such as window move
* mode.
*/
if (window ? (window == display->grab_window) :
(screen == display->grab_screen))
if ((window && window == display->grab_window) || !window)
{
switch (display->grab_op)
{
@ -2824,7 +2797,6 @@ do_choose_window (MetaDisplay *display,
initial_selection = meta_display_get_tab_next (display,
type,
screen,
screen->active_workspace,
NULL,
backward);
@ -3210,10 +3182,9 @@ handle_switch_vt (MetaDisplay *display,
gpointer dummy)
{
gint vt = binding->handler->data;
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
GError *error = NULL;
if (!meta_wayland_compositor_activate_vt (compositor, vt, &error))
if (!meta_activate_vt (vt, &error))
{
g_warning ("Failed to switch VT: %s", error->message);
g_error_free (error);

View File

@ -55,7 +55,6 @@
#include <glib-object.h>
#include <glib-unix.h>
#include <gdk/gdkx.h>
#include <stdlib.h>
#include <sys/types.h>
@ -71,7 +70,6 @@
#include <unistd.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#ifdef HAVE_INTROSPECTION
#include <girepository.h>
@ -80,6 +78,7 @@
#include "x11/session.h"
#include "wayland/meta-wayland.h"
#include "backends/meta-backend.h"
/*
* The exit code we'll return to our parent process when we eventually die.
@ -267,72 +266,6 @@ meta_get_option_context (void)
return ctx;
}
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
* the X fd, but we do have to deal with dispatching events that accumulate
* in the clutter queue. This happens, for example, when clutter generate
* enter/leave events on mouse motion - several events are queued in the
* clutter queue but only one dispatched. It could also happen because of
* explicit calls to clutter_event_put(). We add a very simple custom
* event loop source which is simply responsible for pulling events off
* of the queue and dispatching them before we block for new events.
*/
static gboolean
event_prepare (GSource *source,
gint *timeout_)
{
*timeout_ = -1;
return clutter_events_pending ();
}
static gboolean
event_check (GSource *source)
{
return clutter_events_pending ();
}
static gboolean
event_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterEvent *event = clutter_event_get ();
if (event)
{
clutter_do_event (event);
clutter_event_free (event);
}
return TRUE;
}
static GSourceFuncs event_funcs = {
event_prepare,
event_check,
event_dispatch
};
static void
meta_clutter_init (void)
{
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
if (CLUTTER_INIT_SUCCESS == clutter_init (NULL, NULL))
{
GSource *source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);
}
else
{
meta_fatal ("Unable to initialize Clutter.\n");
}
}
/**
* meta_select_display:
*
@ -504,32 +437,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

@ -1,49 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_PRIVATE_H
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <clutter/clutter.h>
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_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,996 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
/**
* SECTION:idle-monitor
* @title: MetaIdleMonitor
* @short_description: Mutter idle counter (similar to X's IDLETIME)
*/
#include "config.h"
#include <string.h>
#include <clutter/clutter.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
#include "display-private.h"
#include "meta-idle-monitor-private.h"
#include "meta-dbus-idle-monitor.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
struct _MetaIdleMonitor
{
GObject parent_instance;
GHashTable *watches;
GHashTable *alarms;
int device_id;
/* X11 implementation */
Display *display;
int sync_event_base;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
/* Wayland implementation */
guint64 last_event_time;
};
struct _MetaIdleMonitorClass
{
GObjectClass parent_class;
};
typedef struct
{
MetaIdleMonitor *monitor;
guint id;
MetaIdleMonitorWatchFunc callback;
gpointer user_data;
GDestroyNotify notify;
guint64 timeout_msec;
/* x11 */
XSyncAlarm xalarm;
int idle_source_id;
/* wayland */
GSource *timeout_source;
} MetaIdleMonitorWatch;
enum
{
PROP_0,
PROP_DEVICE_ID,
PROP_LAST,
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
static MetaIdleMonitor *device_monitors[256];
static int device_id_max;
static gint64
_xsyncvalue_to_int64 (XSyncValue value)
{
return ((guint64) XSyncValueHigh32 (value)) << 32
| (guint64) XSyncValueLow32 (value);
}
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
static void
fire_watch (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
guint id;
gboolean is_user_active_watch;
monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
id = watch->id;
is_user_active_watch = (watch->timeout_msec == 0);
if (watch->callback)
watch->callback (monitor, id, watch->user_data);
if (is_user_active_watch)
meta_idle_monitor_remove_watch (monitor, id);
g_object_unref (monitor);
}
static XSyncAlarm
_xsync_alarm_set (MetaIdleMonitor *monitor,
XSyncTestType test_type,
guint64 interval,
gboolean want_events)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
guint flags;
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
XSyncIntToValue (&delta, 0);
attr.trigger.counter = monitor->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = want_events;
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
attr.trigger.test_type = test_type;
return XSyncCreateAlarm (monitor->display, flags, &attr);
}
static void
ensure_alarm_rescheduled (Display *dpy,
XSyncAlarm alarm)
{
XSyncAlarmAttributes attr;
/* Some versions of Xorg have an issue where alarms aren't
* always rescheduled. Calling XSyncChangeAlarm, even
* without any attributes, will reschedule the alarm. */
XSyncChangeAlarm (dpy, alarm, 0, &attr);
}
static void
set_alarm_enabled (Display *dpy,
XSyncAlarm alarm,
gboolean enabled)
{
XSyncAlarmAttributes attr;
attr.events = enabled;
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static void
check_x11_watch (gpointer data,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = data;
XSyncAlarm alarm = (XSyncAlarm) user_data;
if (watch->xalarm != alarm)
return;
fire_watch (watch);
}
static void
meta_idle_monitor_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
XSyncAlarm alarm;
GList *watches;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
return;
alarm = alarm_event->alarm;
has_alarm = FALSE;
if (alarm == monitor->user_active_alarm)
{
set_alarm_enabled (monitor->display,
alarm,
FALSE);
has_alarm = TRUE;
}
else if (g_hash_table_contains (monitor->alarms, (gpointer) alarm))
{
ensure_alarm_rescheduled (monitor->display,
alarm);
has_alarm = TRUE;
}
if (has_alarm)
{
watches = g_hash_table_get_values (monitor->watches);
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
g_list_free (watches);
}
}
void
meta_idle_monitor_handle_xevent_all (XEvent *xevent)
{
int i;
for (i = 0; i <= device_id_max; i++)
if (device_monitors[i])
meta_idle_monitor_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}
static char *
counter_name_for_device (int device_id)
{
if (device_id > 0)
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
return g_strdup ("IDLETIME");
}
static XSyncCounter
find_idletime_counter (MetaIdleMonitor *monitor)
{
int i;
int ncounters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
char *counter_name;
counter_name = counter_name_for_device (monitor->device_id);
counters = XSyncListSystemCounters (monitor->display, &ncounters);
for (i = 0; i < ncounters; i++)
{
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
g_free (counter_name);
return counter;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static void
idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
if (watch == NULL)
return;
monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch->xalarm != monitor->user_active_alarm &&
watch->xalarm != None)
{
XSyncDestroyAlarm (monitor->display, watch->xalarm);
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
}
if (watch->timeout_source != NULL)
g_source_destroy (watch->timeout_source);
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatch, watch);
}
static void
init_xsync (MetaIdleMonitor *monitor)
{
monitor->counter = find_idletime_counter (monitor);
/* IDLETIME counter not found? */
if (monitor->counter == None)
{
meta_warning ("IDLETIME counter not found\n");
return;
}
monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
}
static void
meta_idle_monitor_dispose (GObject *object)
{
MetaIdleMonitor *monitor;
monitor = META_IDLE_MONITOR (object);
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
g_clear_pointer (&monitor->alarms, g_hash_table_destroy);
if (monitor->user_active_alarm != None)
{
XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm);
monitor->user_active_alarm = None;
}
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
}
static void
meta_idle_monitor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
g_value_set_int (value, monitor->device_id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
monitor->device_id = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_constructed (GObject *object)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
if (!meta_is_wayland_compositor ())
{
monitor->display = meta_get_display ()->xdisplay;
init_xsync (monitor);
}
}
static void
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_idle_monitor_dispose;
object_class->constructed = meta_idle_monitor_constructed;
object_class->get_property = meta_idle_monitor_get_property;
object_class->set_property = meta_idle_monitor_set_property;
/**
* MetaIdleMonitor:device_id:
*
* The device to listen to idletime on.
*/
obj_props[PROP_DEVICE_ID] =
g_param_spec_int ("device-id",
"Device ID",
"The device to listen to idletime on",
0, 255, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
}
static void
meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
monitor->watches = g_hash_table_new_full (NULL,
NULL,
NULL,
(GDestroyNotify)idle_monitor_watch_free);
monitor->alarms = g_hash_table_new (NULL, NULL);
}
static void
ensure_device_monitor (int device_id)
{
if (device_monitors[device_id])
return;
device_monitors[device_id] = g_object_new (META_TYPE_IDLE_MONITOR, "device-id", device_id, NULL);
device_id_max = MAX (device_id_max, device_id);
}
/**
* meta_idle_monitor_get_core:
*
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
* idletime for all devices. To track device-specific idletime,
* use meta_idle_monitor_get_for_device().
*/
MetaIdleMonitor *
meta_idle_monitor_get_core (void)
{
ensure_device_monitor (0);
return device_monitors[0];
}
/**
* meta_idle_monitor_get_for_device:
* @device_id: the device to get the idle time for.
*
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
* device-specific idletime for @device. To track server-global idletime
* for all devices, use meta_idle_monitor_get_core().
*/
MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id)
{
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
ensure_device_monitor (device_id);
return device_monitors[device_id];
}
static gboolean
wayland_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = user_data;
fire_watch (watch);
g_source_set_ready_time (watch->timeout_source, -1);
return TRUE;
}
static GSourceFuncs wayland_source_funcs = {
NULL, /* prepare */
NULL, /* check */
wayland_dispatch_timeout,
NULL, /* finalize */
};
static gboolean
fire_watch_idle (gpointer data)
{
MetaIdleMonitorWatch *watch = data;
watch->idle_source_id = 0;
fire_watch (watch);
return FALSE;
}
static MetaIdleMonitorWatch *
make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
watch = g_slice_new0 (MetaIdleMonitorWatch);
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (meta_is_wayland_compositor ())
{
if (timeout_msec != 0)
{
GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000);
g_source_attach (source, NULL);
g_source_unref (source);
watch->timeout_source = source;
}
}
else if (monitor->user_active_alarm != None)
{
if (timeout_msec != 0)
{
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
}
else
{
watch->xalarm = monitor->user_active_alarm;
set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
}
}
g_hash_table_insert (monitor->watches,
GUINT_TO_POINTER (watch->id),
watch);
return watch;
}
/**
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (allow-none): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Adds a watch for a specific idle time. The callback will be called
* when the user has accumulated @interval_msec milliseconds of idle time.
* This function will return an ID that can either be passed to
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
* watches apart if you have more than one.
*
* Also note that this function will only care about positive transitions
* (user's idle time exceeding a certain time). If you want to know about
* when the user has become active, use
* meta_idle_monitor_add_user_active_watch().
*/
guint
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
guint64 interval_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
g_return_val_if_fail (interval_msec > 0, 0);
watch = make_watch (monitor,
interval_msec,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (allow-none): The callback to call when the user is
* active again.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Add a one-time watch to know when the user is active again.
* Note that this watch is one-time and will de-activate after the
* function is called, for efficiency purposes. It's most convenient
* to call this when an idle watch, as added by
* meta_idle_monitor_add_idle_watch(), has triggered.
*/
guint
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
watch = make_watch (monitor,
0,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_remove_watch:
* @monitor: A #MetaIdleMonitor
* @id: A watch ID
*
* Removes an idle time watcher, previously added by
* meta_idle_monitor_add_idle_watch() or
* meta_idle_monitor_add_user_active_watch().
*/
void
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
guint id)
{
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);
}
/**
* meta_idle_monitor_get_idletime:
* @monitor: A #MetaIdleMonitor
*
* Returns: The current idle time, in milliseconds, or -1 for not supported
*/
gint64
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
XSyncValue value;
if (meta_is_wayland_compositor ())
{
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
}
else
{
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
return -1;
return _xsyncvalue_to_int64 (value);
}
}
typedef struct {
MetaIdleMonitor *monitor;
GList *fired_watches;
} CheckWaylandClosure;
static gboolean
check_wayland_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = value;
CheckWaylandClosure *closure = user_data;
gboolean steal;
if (watch->timeout_msec == 0)
{
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
steal = TRUE;
}
else
{
g_source_set_ready_time (watch->timeout_source,
closure->monitor->last_event_time +
watch->timeout_msec * 1000);
steal = FALSE;
}
return steal;
}
static void
fire_wayland_watch (gpointer watch,
gpointer data)
{
fire_watch (watch);
}
void
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
{
CheckWaylandClosure closure;
monitor->last_event_time = g_get_monotonic_time ();
closure.monitor = monitor;
closure.fired_watches = NULL;
g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure);
g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL);
g_list_free (closure.fired_watches);
}
static gboolean
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
guint64 idletime;
idletime = meta_idle_monitor_get_idletime (monitor);
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
return TRUE;
}
typedef struct {
MetaDBusIdleMonitor *dbus_monitor;
MetaIdleMonitor *monitor;
char *dbus_name;
guint watch_id;
guint name_watcher_id;
} DBusWatch;
static void
destroy_dbus_watch (gpointer data)
{
DBusWatch *watch = data;
g_object_unref (watch->dbus_monitor);
g_object_unref (watch->monitor);
g_free (watch->dbus_name);
g_bus_unwatch_name (watch->name_watcher_id);
g_slice_free (DBusWatch, watch);
}
static void
dbus_idle_callback (MetaIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
DBusWatch *watch = user_data;
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
watch->dbus_name,
g_dbus_interface_skeleton_get_object_path (skeleton),
"org.gnome.Mutter.IdleMonitor",
"WatchFired",
g_variant_new ("(u)", watch_id),
NULL);
}
static void
name_vanished_callback (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
DBusWatch *watch = user_data;
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
}
static DBusWatch *
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = g_slice_new (DBusWatch);
watch->dbus_monitor = g_object_ref (skeleton);
watch->monitor = g_object_ref (monitor);
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
watch->dbus_name,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL, /* appeared */
name_vanished_callback,
watch, NULL);
return watch;
}
static gboolean
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint64 interval,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
dbus_idle_callback, watch, destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
dbus_idle_callback, watch,
destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint id,
MetaIdleMonitor *monitor)
{
meta_idle_monitor_remove_watch (monitor, id);
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
return TRUE;
}
static void
create_monitor_skeleton (GDBusObjectManagerServer *manager,
MetaIdleMonitor *monitor,
const char *path)
{
MetaDBusIdleMonitor *skeleton;
MetaDBusObjectSkeleton *object;
skeleton = meta_dbus_idle_monitor_skeleton_new ();
g_signal_connect_object (skeleton, "handle-add-idle-watch",
G_CALLBACK (handle_add_idle_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-remove-watch",
G_CALLBACK (handle_remove_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-get-idletime",
G_CALLBACK (handle_get_idletime), monitor, 0);
object = meta_dbus_object_skeleton_new (path);
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
MetaIdleMonitor *monitor;
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
monitor = meta_idle_monitor_get_for_device (device_id);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
create_monitor_skeleton (manager, monitor, path);
g_free (path);
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
g_dbus_object_manager_server_unexport (manager, path);
g_free (path);
g_clear_object (&device_monitors[device_id]);
if (device_id == device_id_max)
device_id_max--;
}
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
GDBusObjectManagerServer *manager;
ClutterDeviceManager *device_manager;
MetaIdleMonitor *monitor;
GSList *devices, *iter;
char *path;
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
/* We never clear the core monitor, as that's supposed to cumulate idle times from
all devices */
monitor = meta_idle_monitor_get_core ();
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
create_monitor_skeleton (manager, monitor, path);
g_free (path);
device_manager = clutter_device_manager_get_default ();
devices = clutter_device_manager_list_devices (device_manager);
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",
G_CALLBACK (on_device_removed), manager, 0);
g_dbus_object_manager_server_set_connection (manager, connection);
}
static void
on_name_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Acquired name %s\n", name);
}
static void
on_name_lost (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Lost or failed to acquire name %s\n", name);
}
void
meta_idle_monitor_init_dbus (void)
{
static int dbus_name_id;
if (dbus_name_id > 0)
return;
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.gnome.Mutter.IdleMonitor",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
(meta_get_replace_current_wm () ?
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL, NULL);
}

View File

@ -36,7 +36,7 @@
#include <X11/Xutil.h>
#include "stack-tracker.h"
#include "ui.h"
#include "monitor-private.h"
#include "meta-monitor-manager.h"
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
gpointer user_data);
@ -116,9 +116,6 @@ struct _MetaScreen
guint all_keys_grabbed : 1;
int closing;
/* Managed by compositor.c */
gpointer compositor_data;
/* Instead of unmapping withdrawn windows we can leave them mapped
* and restack them below a guard window. When using a compositor

View File

@ -43,6 +43,7 @@
#include "mutter-enum-types.h"
#include "core.h"
#include "meta-cursor-tracker-private.h"
#include "backends/x11/meta-cursor-tracker-x11.h"
#include <X11/extensions/Xinerama.h>
@ -707,7 +708,6 @@ meta_screen_new (MetaDisplay *display,
screen->columns_of_workspaces = -1;
screen->vertical_workspaces = FALSE;
screen->starting_corner = META_SCREEN_TOPLEFT;
screen->compositor_data = NULL;
screen->guard_window = None;
reload_monitor_infos (screen);
@ -808,8 +808,7 @@ meta_screen_free (MetaScreen *screen,
meta_display_grab (display);
meta_compositor_unmanage_screen (screen->display->compositor,
screen);
meta_compositor_unmanage (screen->display->compositor);
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
@ -900,28 +899,6 @@ meta_screen_manage_all_windows (MetaScreen *screen)
meta_stack_thaw (screen->stack);
}
/**
* meta_screen_for_x_screen:
* @xscreen: an X screen structure.
*
* Gets the #MetaScreen corresponding to an X screen structure.
*
* Return value: (transfer none): the #MetaScreen for the X screen
* %NULL if Metacity is not managing the screen.
*/
MetaScreen*
meta_screen_for_x_screen (Screen *xscreen)
{
MetaDisplay *display;
display = meta_display_for_x_display (DisplayOfScreen (xscreen));
if (display == NULL)
return NULL;
return meta_display_screen_for_x_screen (display, xscreen);
}
static void
prefs_changed_callback (MetaPreference pref,
gpointer data)
@ -1405,6 +1382,26 @@ update_focus_mode (MetaScreen *screen)
/* nothing to do anymore */ ;
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
MetaDisplay *display = screen->display;
MetaCursor cursor = screen->current_cursor;
Cursor xcursor;
MetaCursorReference *cursor_ref;
cursor_ref = meta_cursor_tracker_get_cursor_from_theme (screen->cursor_tracker, cursor);
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor_ref);
meta_cursor_reference_unref (cursor_ref);
/* Set a cursor for X11 applications that don't specify their own */
xcursor = meta_display_create_x_cursor (display, cursor);
XDefineCursor (display->xdisplay, screen->xroot, xcursor);
XFlush (display->xdisplay);
XFreeCursor (display->xdisplay, xcursor);
}
void
meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor)
@ -1413,14 +1410,7 @@ meta_screen_set_cursor (MetaScreen *screen,
return;
screen->current_cursor = cursor;
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
screen->current_cursor);
meta_screen_update_cursor (screen);
}
static gboolean
@ -1461,11 +1451,10 @@ meta_screen_update_tile_preview_timeout (gpointer data)
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);
window, &tile_rect, monitor);
}
else
meta_compositor_hide_tile_preview (screen->display->compositor,
screen);
meta_compositor_hide_tile_preview (screen->display->compositor);
return FALSE;
}
@ -1501,8 +1490,7 @@ meta_screen_hide_tile_preview (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);
meta_compositor_hide_tile_preview (screen->display->compositor);
}
MetaWindow*
@ -2520,7 +2508,6 @@ on_monitors_changed (MetaMonitorManager *manager,
}
meta_compositor_sync_screen_size (screen->display->compositor,
screen,
screen->rect.width, screen->rect.height);
/* Queue a resize on all the windows */
@ -3061,24 +3048,6 @@ meta_screen_get_size (MetaScreen *screen,
*height = screen->rect.height;
}
/**
* meta_screen_get_compositor_data: (skip)
* @screen: A #MetaScreen
*
*/
gpointer
meta_screen_get_compositor_data (MetaScreen *screen)
{
return screen->compositor_data;
}
void
meta_screen_set_compositor_data (MetaScreen *screen,
gpointer compositor)
{
screen->compositor_data = compositor;
}
void
meta_screen_set_cm_selection (MetaScreen *screen)
{
@ -3337,7 +3306,10 @@ gboolean
meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent)
{
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent))
if (meta_is_wayland_compositor ())
return FALSE;
if (meta_cursor_tracker_x11_handle_xevent (META_CURSOR_TRACKER_X11 (screen->cursor_tracker), xevent))
return TRUE;
return FALSE;

View File

@ -1246,7 +1246,6 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
}
meta_compositor_sync_stack (tracker->screen->display->compositor,
tracker->screen,
meta_windows);
g_list_free (meta_windows);

View File

@ -220,10 +220,18 @@ struct _MetaWindow
*/
guint hidden : 1;
/* Whether the compositor thinks the window is visible
/* Whether the compositor thinks the window is visible.
* This should match up with calls to meta_compositor_show_window /
* meta_compositor_hide_window.
*/
guint visible_to_compositor : 1;
/* Whether the compositor knows about the window.
* This should match up with calls to meta_compositor_add_window /
* meta_compositor_remove_window.
*/
guint known_to_compositor : 1;
/* When we next show or hide the window, what effect we should
* tell the compositor to perform.
*/

View File

@ -867,6 +867,7 @@ _meta_window_shared_new (MetaDisplay *display,
window->iconic = FALSE;
window->mapped = attrs->map_state != IsUnmapped;
window->hidden = FALSE;
window->known_to_compositor = FALSE;
window->visible_to_compositor = FALSE;
window->pending_compositor_effect = effect;
/* if already mapped, no need to worry about focus-on-first-time-showing */
@ -1195,6 +1196,7 @@ _meta_window_shared_new (MetaDisplay *display,
}
meta_compositor_add_window (screen->display->compositor, window);
window->known_to_compositor = TRUE;
/* Sync stack changes */
meta_stack_thaw (window->screen->stack);
@ -1248,7 +1250,7 @@ meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface)
{
XWindowAttributes attrs;
MetaScreen *scr = display->screens->data;
MetaScreen *scr = display->screen;
MetaWindow *window;
attrs.x = 0;
@ -1280,7 +1282,6 @@ meta_window_wayland_new (MetaDisplay *display,
* X requests (passing a window xid of None) until we thoroughly audit all
* the code to make sure it knows about non X based clients...
*/
meta_error_trap_push (display); /* Push a trap over all of window
* creation, to reduce XSync() calls
*/
@ -1467,13 +1468,17 @@ meta_window_unmanage (MetaWindow *window,
/* This needs to happen for both Wayland and XWayland clients,
* so it can't be in MetaWindowWayland. */
if (window->surface)
meta_wayland_surface_window_unmanaged (window->surface);
meta_wayland_surface_set_window (window->surface, NULL);
if (window->visible_to_compositor)
meta_compositor_hide_window (window->display->compositor, window,
META_COMP_EFFECT_DESTROY);
{
window->visible_to_compositor = FALSE;
meta_compositor_hide_window (window->display->compositor, window,
META_COMP_EFFECT_DESTROY);
}
meta_compositor_remove_window (window->display->compositor, window);
window->known_to_compositor = FALSE;
if (window->display->window_with_menu == window)
{
@ -4329,7 +4334,7 @@ meta_window_move_resize_internal (MetaWindow *window,
newx, newy, window->rect.width, window->rect.height,
window->user_rect.x, window->user_rect.y,
window->user_rect.width, window->user_rect.height);
if (window->visible_to_compositor)
if (window->known_to_compositor)
meta_compositor_sync_window_geometry (window->display->compositor,
window,
did_placement);

View File

@ -665,7 +665,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
meta_screen_free_workspace_layout (&layout1);
meta_screen_free_workspace_layout (&layout2);
meta_compositor_switch_workspace (comp, screen, old, workspace, direction);
meta_compositor_switch_workspace (comp, old, workspace, direction);
/* This needs to be done after telling the compositor we are switching
* workspaces since focusing a window will cause it to be immediately

View File

@ -57,10 +57,8 @@ typedef enum
MetaCompositor *meta_compositor_new (MetaDisplay *display);
void meta_compositor_destroy (MetaCompositor *compositor);
void meta_compositor_manage_screen (MetaCompositor *compositor,
MetaScreen *screen);
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen);
void meta_compositor_manage (MetaCompositor *compositor);
void meta_compositor_unmanage (MetaCompositor *compositor);
void meta_compositor_window_shape_changed (MetaCompositor *compositor,
MetaWindow *window);
@ -74,7 +72,6 @@ gboolean meta_compositor_process_event (MetaCompositor *compositor,
MetaWindow *window);
gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor,
MetaScreen *screen,
MetaKeyBinding *binding);
void meta_compositor_add_window (MetaCompositor *compositor,
@ -88,7 +85,6 @@ void meta_compositor_hide_window (MetaCompositor *compositor,
MetaWindow *window,
MetaCompEffect effect);
void meta_compositor_switch_workspace (MetaCompositor *compositor,
MetaScreen *screen,
MetaWorkspace *from,
MetaWorkspace *to,
MetaMotionDirection direction);
@ -113,10 +109,8 @@ void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
gboolean no_delay_frame);
void meta_compositor_sync_stack (MetaCompositor *compositor,
MetaScreen *screen,
GList *stack);
void meta_compositor_sync_screen_size (MetaCompositor *compositor,
MetaScreen *screen,
guint width,
guint height);
@ -124,11 +118,9 @@ void meta_compositor_flash_screen (MetaCompositor *compositor,
MetaScreen *screen);
void meta_compositor_show_tile_preview (MetaCompositor *compositor,
MetaScreen *screen,
MetaWindow *window,
MetaRectangle *tile_rect,
int tile_monitor_number);
void meta_compositor_hide_tile_preview (MetaCompositor *compositor,
MetaScreen *screen);
void meta_compositor_hide_tile_preview (MetaCompositor *compositor);
#endif /* META_COMPOSITOR_H */

View File

@ -73,12 +73,9 @@ int meta_display_get_xinput_opcode (MetaDisplay *display);
gboolean meta_display_supports_extended_barriers (MetaDisplay *display);
Display *meta_display_get_xdisplay (MetaDisplay *display);
MetaCompositor *meta_display_get_compositor (MetaDisplay *display);
GSList *meta_display_get_screens (MetaDisplay *display);
gboolean meta_display_has_shape (MetaDisplay *display);
MetaScreen *meta_display_screen_for_root (MetaDisplay *display,
Window xroot);
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
@ -104,14 +101,12 @@ GList* meta_display_get_tab_list (MetaDisplay *display,
MetaWindow* meta_display_get_tab_next (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
MetaWindow *window,
gboolean backward);
MetaWindow* meta_display_get_tab_current (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace);
gboolean meta_display_begin_grab_op (MetaDisplay *display,

View File

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

View File

@ -91,7 +91,6 @@ void meta_background_load_gradient (MetaBackground *self,
ClutterColor *second_color);
void meta_background_load_color (MetaBackground *self,
ClutterColor *color);
void meta_background_load_still_frame (MetaBackground *self);
void meta_background_load_file_async (MetaBackground *self,
const char *filename,
GDesktopBackgroundStyle style,

View File

@ -405,7 +405,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
MetaScreen *meta_plugin_get_screen (MetaPlugin *plugin);
void _meta_plugin_set_screen (MetaPlugin *plugin, MetaScreen *screen);
void _meta_plugin_set_compositor (MetaPlugin *plugin, MetaCompositor *compositor);
/* XXX: Putting this in here so it's in the public header. */
void meta_plugin_manager_set_plugin_type (GType gtype);

View File

@ -44,12 +44,6 @@ void meta_screen_get_size (MetaScreen *screen,
int *width,
int *height);
gpointer meta_screen_get_compositor_data (MetaScreen *screen);
void meta_screen_set_compositor_data (MetaScreen *screen,
gpointer info);
MetaScreen *meta_screen_for_x_screen (Screen *xscreen);
void meta_screen_set_cm_selection (MetaScreen *screen);
void meta_screen_unset_cm_selection (MetaScreen *screen);

View File

@ -228,58 +228,17 @@ maybe_redirect_mouse_event (XEvent *xevent)
return TRUE;
}
typedef struct _EventFunc EventFunc;
struct _EventFunc
{
MetaEventFunc func;
gpointer data;
};
static EventFunc *ef = NULL;
static GdkFilterReturn
filter_func (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
ui_filter_func (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
g_return_val_if_fail (ef != NULL, GDK_FILTER_CONTINUE);
if ((* ef->func) (xevent, ef->data) ||
maybe_redirect_mouse_event (xevent))
if (maybe_redirect_mouse_event (xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
}
void
meta_ui_add_event_func (Display *xdisplay,
MetaEventFunc func,
gpointer data)
{
g_return_if_fail (ef == NULL);
ef = g_new (EventFunc, 1);
ef->func = func;
ef->data = data;
gdk_window_add_filter (NULL, filter_func, ef);
}
/* removal is by data due to proxy function */
void
meta_ui_remove_event_func (Display *xdisplay,
MetaEventFunc func,
gpointer data)
{
g_return_if_fail (ef != NULL);
gdk_window_remove_filter (NULL, filter_func, ef);
g_free (ef);
ef = NULL;
}
MetaUI*
meta_ui_new (Display *xdisplay,
Screen *screen)
@ -294,6 +253,8 @@ meta_ui_new (Display *xdisplay,
gdisplay = gdk_x11_lookup_xdisplay (xdisplay);
g_assert (gdisplay == gdk_display_get_default ());
gdk_window_add_filter (NULL, ui_filter_func, NULL);
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
/* GTK+ needs the frame-sync protocol to work in order to properly
* handle style changes. This means that the dummy widget we create
@ -303,6 +264,8 @@ meta_ui_new (Display *xdisplay,
*/
gtk_widget_show (GTK_WIDGET (ui->frames));
gdk_window_add_filter (NULL, ui_filter_func, NULL);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
return ui;
@ -318,6 +281,8 @@ meta_ui_free (MetaUI *ui)
gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL);
gdk_window_remove_filter (NULL, ui_filter_func, NULL);
g_free (ui);
}

View File

@ -46,13 +46,6 @@ Display* meta_ui_get_display (void);
gint meta_ui_get_screen_number (void);
void meta_ui_add_event_func (Display *xdisplay,
MetaEventFunc func,
gpointer data);
void meta_ui_remove_event_func (Display *xdisplay,
MetaEventFunc func,
gpointer data);
MetaUI* meta_ui_new (Display *xdisplay,
Screen *screen);
void meta_ui_free (MetaUI *ui);

View File

@ -27,7 +27,6 @@
#include <cairo.h>
#include "window-private.h"
#include "meta-weston-launch.h"
#include <meta/meta-cursor-tracker.h>
#include "meta-wayland.h"
@ -85,8 +84,6 @@ struct _MetaWaylandCompositor
MetaXWaylandManager xwayland_manager;
MetaLauncher *launcher;
MetaWaylandSeat *seat;
};

View File

@ -38,6 +38,7 @@
#include "meta-shaped-texture-private.h"
#include "meta-wayland-stage.h"
#include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
#include "meta-surface-actor-wayland.h"
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
@ -68,20 +69,26 @@ set_cursor_surface (MetaWaylandSeat *seat,
void
meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
{
struct wl_resource *buffer;
MetaCursorReference *cursor;
if (seat->cursor_tracker == NULL)
return;
if (seat->cursor_surface && seat->cursor_surface->buffer)
buffer = seat->cursor_surface->buffer->resource;
{
struct wl_resource *buffer = seat->cursor_surface->buffer->resource;
cursor = meta_cursor_tracker_get_cursor_from_buffer (seat->cursor_tracker,
buffer,
seat->hotspot_x,
seat->hotspot_y);
}
else
buffer = NULL;
cursor = NULL;
meta_cursor_tracker_set_window_cursor (seat->cursor_tracker,
buffer,
seat->hotspot_x,
seat->hotspot_y);
meta_cursor_tracker_set_window_cursor (seat->cursor_tracker, cursor);
if (cursor)
meta_cursor_reference_unref (cursor);
}
static void
@ -109,8 +116,16 @@ pointer_set_cursor (struct wl_client *client,
meta_wayland_seat_update_cursor_surface (seat);
}
static void
pointer_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_pointer_interface pointer_interface = {
pointer_set_cursor
pointer_set_cursor,
pointer_release,
};
static void
@ -131,6 +146,17 @@ seat_get_pointer (struct wl_client *client,
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
}
static void
keyboard_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_keyboard_interface keyboard_interface = {
keyboard_release,
};
static void
seat_get_keyboard (struct wl_client *client,
struct wl_resource *resource,
@ -361,9 +387,9 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
if (seat->cursor_tracker)
{
meta_cursor_tracker_update_position (seat->cursor_tracker,
wl_fixed_to_int (seat->pointer.x),
wl_fixed_to_int (seat->pointer.y));
meta_cursor_tracker_native_update_position (META_CURSOR_TRACKER_NATIVE (seat->cursor_tracker),
wl_fixed_to_int (seat->pointer.x),
wl_fixed_to_int (seat->pointer.y));
if (seat->pointer.current == NULL)
meta_cursor_tracker_unset_window_cursor (seat->cursor_tracker);

View File

@ -30,6 +30,7 @@
#include "meta/meta-window-actor.h"
#include "meta/meta-shaped-texture.h"
#include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-tracker-native.h"
G_DEFINE_TYPE (MetaWaylandStage, meta_wayland_stage, CLUTTER_TYPE_STAGE);
@ -42,7 +43,7 @@ meta_wayland_stage_paint (ClutterActor *actor)
compositor = meta_wayland_compositor_get_default ();
if (compositor->seat->cursor_tracker)
meta_cursor_tracker_paint (compositor->seat->cursor_tracker);
meta_cursor_tracker_native_paint (META_CURSOR_TRACKER_NATIVE (compositor->seat->cursor_tracker));
}
static void
@ -62,7 +63,7 @@ meta_wayland_stage_init (MetaWaylandStage *self)
ClutterActor *
meta_wayland_stage_new (void)
{
return g_object_new (META_WAYLAND_TYPE_STAGE,
return g_object_new (META_TYPE_WAYLAND_STAGE,
"cursor-visible", FALSE,
NULL);
}

View File

@ -27,26 +27,12 @@
G_BEGIN_DECLS
#define META_WAYLAND_TYPE_STAGE \
(meta_wayland_stage_get_type())
#define META_WAYLAND_STAGE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
META_WAYLAND_TYPE_STAGE, \
MetaWaylandStage))
#define META_WAYLAND_STAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
META_WAYLAND_TYPE_STAGE, \
MetaWaylandStageClass))
#define META_WAYLAND_IS_STAGE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
META_WAYLAND_TYPE_STAGE))
#define META_WAYLAND_IS_STAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
META_WAYLAND_TYPE_STAGE))
#define META_WAYLAND_STAGE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
META_WAYLAND_STAGE, \
MetaWaylandStageClass))
#define META_TYPE_WAYLAND_STAGE (meta_wayland_stage_get_type ())
#define META_WAYLAND_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WAYLAND_STAGE, MetaWaylandStage))
#define META_WAYLAND_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WAYLAND_STAGE, MetaWaylandStageClass))
#define META_IS_WAYLAND_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WAYLAND_STAGE))
#define META_IS_WAYLAND_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WAYLAND_STAGE))
#define META_WAYLAND_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WAYLAND_STAGE, MetaWaylandStageClass))
typedef struct _MetaWaylandStage MetaWaylandStage;
typedef struct _MetaWaylandStageClass MetaWaylandStageClass;

View File

@ -55,8 +55,6 @@
#include <meta/types.h>
#include <meta/main.h>
#include "frame.h"
#include "meta-idle-monitor-private.h"
#include "monitor-private.h"
#include "meta-surface-actor.h"
#include "meta-surface-actor-wayland.h"
@ -83,8 +81,8 @@ surface_set_buffer (MetaWaylandSurface *surface,
if (surface->buffer)
{
meta_wayland_buffer_unref (surface->buffer);
wl_list_remove (&surface->buffer_destroy_listener.link);
meta_wayland_buffer_unref (surface->buffer);
}
surface->buffer = buffer;
@ -120,17 +118,17 @@ surface_process_damage (MetaWaylandSurface *surface,
}
static void
meta_wayland_surface_destroy (struct wl_client *client,
struct wl_resource *resource)
wl_surface_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static void
meta_wayland_surface_attach (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *buffer_resource,
gint32 dx, gint32 dy)
wl_surface_attach (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *buffer_resource,
gint32 dx, gint32 dy)
{
MetaWaylandSurface *surface =
wl_resource_get_user_data (surface_resource);
@ -160,12 +158,12 @@ meta_wayland_surface_attach (struct wl_client *client,
}
static void
meta_wayland_surface_damage (struct wl_client *client,
struct wl_resource *surface_resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
wl_surface_damage (struct wl_client *client,
struct wl_resource *surface_resource,
gint32 x,
gint32 y,
gint32 width,
gint32 height)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
cairo_rectangle_int_t rectangle = { x, y, width, height };
@ -188,9 +186,9 @@ destroy_frame_callback (struct wl_resource *callback_resource)
}
static void
meta_wayland_surface_frame (struct wl_client *client,
struct wl_resource *surface_resource,
guint32 callback_id)
wl_surface_frame (struct wl_client *client,
struct wl_resource *surface_resource,
guint32 callback_id)
{
MetaWaylandFrameCallback *callback;
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
@ -208,9 +206,9 @@ meta_wayland_surface_frame (struct wl_client *client,
}
static void
meta_wayland_surface_set_opaque_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
wl_surface_set_opaque_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
@ -227,9 +225,9 @@ meta_wayland_surface_set_opaque_region (struct wl_client *client,
}
static void
meta_wayland_surface_set_input_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
wl_surface_set_input_region (struct wl_client *client,
struct wl_resource *surface_resource,
struct wl_resource *region_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
@ -509,8 +507,8 @@ commit_double_buffered_state (MetaWaylandSurface *surface,
}
static void
meta_wayland_surface_commit (struct wl_client *client,
struct wl_resource *resource)
wl_surface_commit (struct wl_client *client,
struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@ -522,45 +520,42 @@ meta_wayland_surface_commit (struct wl_client *client,
}
static void
meta_wayland_surface_set_buffer_transform (struct wl_client *client,
struct wl_resource *resource,
int32_t transform)
wl_surface_set_buffer_transform (struct wl_client *client,
struct wl_resource *resource,
int32_t transform)
{
g_warning ("TODO: support set_buffer_transform request");
}
static void
meta_wayland_surface_set_buffer_scale (struct wl_client *client,
struct wl_resource *resource,
int scale)
wl_surface_set_buffer_scale (struct wl_client *client,
struct wl_resource *resource,
int scale)
{
if (scale != 1)
g_warning ("TODO: support set_buffer_scale request");
}
const struct wl_surface_interface meta_wayland_surface_interface = {
meta_wayland_surface_destroy,
meta_wayland_surface_attach,
meta_wayland_surface_damage,
meta_wayland_surface_frame,
meta_wayland_surface_set_opaque_region,
meta_wayland_surface_set_input_region,
meta_wayland_surface_commit,
meta_wayland_surface_set_buffer_transform,
meta_wayland_surface_set_buffer_scale
const struct wl_surface_interface meta_wayland_wl_surface_interface = {
wl_surface_destroy,
wl_surface_attach,
wl_surface_damage,
wl_surface_frame,
wl_surface_set_opaque_region,
wl_surface_set_input_region,
wl_surface_commit,
wl_surface_set_buffer_transform,
wl_surface_set_buffer_scale
};
void
meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface)
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
}
gboolean has_window = (window != NULL);
void
meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE);
surface->window = NULL;
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), has_window);
surface->window = window;
}
static void
@ -614,7 +609,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface->compositor = compositor;
surface->resource = wl_resource_create (client, &wl_surface_interface, version, id);
wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, wl_surface_destructor);
wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, wl_surface_destructor);
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
@ -911,6 +906,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->xdg_surface,
META_XDG_SURFACE_VERSION,
@ -925,8 +921,8 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
return;
}
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
static void
@ -964,6 +960,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWindow *window;
if (parent_surf == NULL || parent_surf->window == NULL)
return;
@ -981,15 +978,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
return;
}
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
surface->window->rect.x = parent_surf->window->rect.x + x;
surface->window->rect.y = parent_surf->window->rect.y + y;
surface->window->showing_for_first_time = FALSE;
surface->window->placed = TRUE;
meta_window_set_transient_for (surface->window, parent_surf->window);
window = meta_window_wayland_new (meta_get_display (), surface);
window->rect.x = parent_surf->window->rect.x + x;
window->rect.y = parent_surf->window->rect.y + y;
window->showing_for_first_time = FALSE;
window->placed = TRUE;
meta_window_set_transient_for (window, parent_surf->window);
meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU);
meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
meta_wayland_surface_set_window (surface, window);
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
}
@ -1272,6 +1269,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWindow *window;
if (!create_surface_extension (&surface->wl_shell_surface,
META_WL_SHELL_SURFACE_VERSION,
@ -1286,8 +1284,8 @@ wl_shell_get_shell_surface (struct wl_client *client,
return;
}
meta_wayland_surface_make_toplevel (surface);
surface->window = meta_window_wayland_new (meta_get_display (), surface);
window = meta_window_wayland_new (meta_get_display (), surface);
meta_wayland_surface_set_window (surface, window);
}
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {

View File

@ -111,8 +111,8 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
guint32 id,
guint32 version);
void meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface);
void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface);
void meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window);
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int width,

View File

@ -38,7 +38,7 @@
#define META_WL_COMPOSITOR_VERSION 3
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
#define META_WL_SEAT_VERSION 3
#define META_WL_OUTPUT_VERSION 2
#define META_XSERVER_VERSION 1
#define META_GTK_SHELL_VERSION 1
@ -49,8 +49,8 @@
#define META_WL_DATA_SOURCE_VERSION 1 /* from wl_data_device */
#define META_WL_DATA_DEVICE_VERSION 1 /* from wl_data_device_manager */
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
#define META_WL_POINTER_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */

View File

@ -37,6 +37,8 @@
#include <wayland-server.h>
#include "backends/meta-backend.h"
#include "meta-wayland-private.h"
#include "meta-xwayland-private.h"
#include "meta-wayland-stage.h"
@ -51,9 +53,7 @@
#include <meta/types.h>
#include <meta/main.h>
#include "frame.h"
#include "meta-idle-monitor-private.h"
#include "meta-weston-launch.h"
#include "monitor-private.h"
#include "meta-monitor-manager.h"
static MetaWaylandCompositor _meta_wayland_compositor;
@ -520,30 +520,6 @@ void
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
const ClutterEvent *event)
{
ClutterInputDevice *device, *source_device;
MetaIdleMonitor *core_monitor, *device_monitor;
int device_id;
device = clutter_event_get_device (event);
if (device == NULL)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_reset_idletime (core_monitor);
meta_idle_monitor_reset_idletime (device_monitor);
source_device = clutter_event_get_source_device (event);
if (source_device != device)
{
device_id = clutter_input_device_get_device_id (device);
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_reset_idletime (device_monitor);
}
meta_wayland_seat_update (compositor->seat, event);
}
@ -575,14 +551,13 @@ set_gnome_env (const char *name,
const char *value)
{
GDBusConnection *session_bus;
GError *error;
GError *error = NULL;
setenv (name, value, TRUE);
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_assert (session_bus);
error = NULL;
g_dbus_connection_call_sync (session_bus,
"org.gnome.SessionManager",
"/org/gnome/SessionManager",
@ -594,8 +569,10 @@ set_gnome_env (const char *name,
-1, NULL, &error);
if (error)
{
meta_warning ("Failed to set environment variable %s for gnome-session: %s\n", name, error->message);
g_clear_error (&error);
if (g_strcmp0 (g_dbus_error_get_remote_error (error), "org.gnome.SessionManager.NotInInitialization") != 0)
meta_warning ("Failed to set environment variable %s for gnome-session: %s\n", name, error->message);
g_error_free (error);
}
}
@ -651,15 +628,7 @@ meta_wayland_init (void)
clutter_wayland_set_compositor_display (compositor->wayland_display);
/* If we're running on bare metal, we're a display server,
* so start talking to weston-launch. */
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
compositor->launcher = meta_launcher_new ();
#endif
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Failed to initialize Clutter");
meta_clutter_init ();
meta_monitor_manager_initialize ();
monitors = meta_monitor_manager_get ();
@ -711,38 +680,4 @@ meta_wayland_finalize (void)
compositor = meta_wayland_compositor_get_default ();
meta_xwayland_stop (&compositor->xwayland_manager);
if (compositor->launcher)
meta_launcher_free (compositor->launcher);
}
gboolean
meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
int vt,
GError **error)
{
if (compositor->launcher)
{
return meta_launcher_activate_vt (compositor->launcher, vt, error);
}
else
{
g_debug ("Ignoring VT switch keybinding, not running as display server");
return TRUE;
}
}
gboolean
meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
GError **error)
{
if (compositor->launcher)
{
return meta_launcher_activate_vt (compositor->launcher, -1, error);
}
else
{
g_debug ("Ignoring activate_session, not running as display server");
return TRUE;
}
}

View File

@ -43,11 +43,5 @@ void meta_wayland_compositor_update (MetaWaylandComp
const ClutterEvent *event);
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
int vt,
GError **error);
gboolean meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
GError **error);
#endif

View File

@ -1,3 +1,5 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* X Wayland Support
*
@ -19,8 +21,11 @@
* 02111-1307, USA.
*/
#include <glib.h>
#include "config.h"
#include "meta-xwayland-private.h"
#include <glib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
@ -29,10 +34,31 @@
#include <sys/wait.h>
#include <stdlib.h>
#include "meta-xwayland-private.h"
#include "meta-window-actor-private.h"
#include "xserver-server-protocol.h"
static void
xserver_finished_init (MetaXWaylandManager *manager);
static void
associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface)
{
MetaDisplay *display = window->display;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_set_window (surface, window);
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
}
static void
xserver_set_window_id (struct wl_client *client,
struct wl_resource *compositor_resource,
@ -47,19 +73,7 @@ xserver_set_window_id (struct wl_client *client,
if (!window)
return;
/* If the window has an existing surface, like if we're
* undecorating or decorating the window, then we need
* to detach the window from its old surface.
*/
if (window->surface)
window->surface->window = NULL;
meta_wayland_surface_make_toplevel (surface);
surface->window = window;
window->surface = surface;
meta_compositor_window_surface_changed (display->compositor, window);
associate_window_with_surface (window, surface);
}
static const struct xserver_interface xserver_implementation = {
@ -93,12 +107,7 @@ bind_xserver (struct wl_client *client,
* manager. */
wl_client_flush (client);
/* At this point xwayland is all setup to start accepting
* connections so we can quit the transient initialization mainloop
* and unblock meta_wayland_init() to continue initializing mutter.
* */
g_main_loop_quit (manager->init_loop);
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
xserver_finished_init (manager);
}
static char *
@ -145,7 +154,6 @@ create_lockfile (int display, int *display_out)
if (kill (other, 0) < 0 && errno == ESRCH)
{
g_warning ("unlinking stale lock file %s", filename);
if (unlink (filename) < 0)
{
const char *msg = strerror (errno);
@ -207,8 +215,7 @@ bind_to_abstract_socket (int display)
size = offsetof (struct sockaddr_un, sun_path) + name_size;
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
g_warning ("failed to bind to @%s: %s\n",
addr.sun_path + 1, strerror (errno));
g_warning ("failed to bind to @%s: %m", addr.sun_path + 1);
close (fd);
return -1;
}
@ -240,8 +247,7 @@ bind_to_unix_socket (int display)
unlink (addr.sun_path);
if (bind (fd, (struct sockaddr *) &addr, size) < 0)
{
char *msg = strerror (errno);
g_warning ("failed to bind to %s (%s)\n", addr.sun_path, msg);
g_warning ("failed to bind to %s: %m\n", addr.sun_path);
close (fd);
return -1;
}
@ -256,18 +262,6 @@ bind_to_unix_socket (int display)
return fd;
}
static void
uncloexec (gpointer user_data)
{
int fd = GPOINTER_TO_INT (user_data);
/* Make sure the client end of the socket pair doesn't get closed
* when we exec xwayland. */
int flags = fcntl (fd, F_GETFD);
if (flags != -1)
fcntl (fd, F_SETFD, flags & ~FD_CLOEXEC);
}
static void
xserver_died (GPid pid,
gint status,
@ -293,20 +287,11 @@ x_io_error (Display *display)
return 0;
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
static gboolean
choose_xdisplay (MetaXWaylandManager *manager)
{
int display = 0;
char *lockfile = NULL;
int sp[2];
pid_t pid;
char **env;
char *fd_string;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
manager, bind_xserver);
do
{
@ -344,60 +329,85 @@ meta_xwayland_start (MetaXWaylandManager *manager,
while (1);
manager->display_index = display;
manager->display_name = g_strdup_printf (":%d", manager->display_index);
manager->lockfile = lockfile;
return TRUE;
}
static void
xserver_finished_init (MetaXWaylandManager *manager)
{
/* At this point xwayland is all setup to start accepting
* connections so we can quit the transient initialization mainloop
* and unblock meta_wayland_init() to continue initializing mutter.
* */
g_main_loop_quit (manager->init_loop);
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
}
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
int sp[2];
int fd;
if (!choose_xdisplay (manager))
return FALSE;
wl_global_create (wl_display, &xserver_interface,
META_XSERVER_VERSION,
manager, bind_xserver);
/* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sp) < 0)
{
g_warning ("socketpair failed\n");
unlink (lockfile);
unlink (manager->lockfile);
return 1;
}
env = g_get_environ ();
fd_string = g_strdup_printf ("%d", sp[1]);
env = g_environ_setenv (env, "WAYLAND_SOCKET", fd_string, TRUE);
g_free (fd_string);
manager->pid = fork ();
if (manager->pid == 0)
{
char socket_fd[8];
manager->display_name = g_strdup_printf (":%d", manager->display_index);
/* We passed SOCK_CLOEXEC, so dup the FD so it isn't
* closed on exec.. */
fd = dup (sp[1]);
snprintf (socket_fd, sizeof (socket_fd), "%d", fd);
setenv ("WAYLAND_SOCKET", socket_fd, TRUE);
{
GError *error = NULL;
gchar *args[] = { XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten",
"all",
NULL };
/* xwayland, please. */
if (getenv ("XWAYLAND_STFU"))
{
int dev_null;
dev_null = open ("/dev/null", O_WRONLY);
if (g_spawn_async (NULL, /* cwd */
args,
env,
G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
G_SPAWN_DO_NOT_REAP_CHILD,
uncloexec,
GINT_TO_POINTER (sp[1]),
&pid,
&error))
{
g_message ("forked X server, pid %d\n", pid);
dup2 (dev_null, STDOUT_FILENO);
dup2 (dev_null, STDERR_FILENO);
}
close (sp[1]);
manager->client = wl_client_create (wl_display, sp[0]);
if (execl (XWAYLAND_PATH, XWAYLAND_PATH,
manager->display_name,
"-wayland",
"-rootless",
"-noreset",
"-nolisten", "all",
NULL) < 0)
{
g_error ("Failed to spawn XWayland: %m");
}
}
else if (manager->pid == -1)
{
g_error ("Failed to fork: %m");
}
manager->pid = pid;
g_child_watch_add (pid, xserver_died, NULL);
}
else
{
g_error ("Failed to fork for xwayland server: %s", error->message);
}
}
g_strfreev (env);
g_child_watch_add (manager->pid, xserver_died, NULL);
manager->client = wl_client_create (wl_display, sp[0]);
/* We need to run a mainloop until we know xwayland has a binding
* for our xserver interface at which point we can assume it's

View File

@ -92,7 +92,13 @@ meta_window_wayland_delete (MetaWindow *window,
static void
meta_window_wayland_kill (MetaWindow *window)
{
/* TODO */
MetaWaylandSurface *surface = window->surface;
struct wl_resource *resource = surface->resource;
/* Send the client an unrecoverable error to kill the client. */
wl_resource_post_error (resource,
WL_DISPLAY_ERROR_NO_MEMORY,
"User requested that we kill you. Sorry. Don't take it too personally.");
}
static void

View File

@ -1816,7 +1816,7 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
"and will have to be restarted manually next time "
"you log in."),
"240",
meta_get_display()->active_screen->screen_name,
meta_get_display()->screen->screen_name,
NULL, NULL, NULL,
None,
columns,

View File

@ -2227,9 +2227,8 @@ meta_window_x11_new (MetaDisplay *display,
gboolean must_be_viewable,
MetaCompEffect effect)
{
MetaScreen *screen = display->screen;
XWindowAttributes attrs;
MetaScreen *screen = NULL;
GSList *tmp;
gulong existing_wm_state;
MetaWindow *window = NULL;
gulong event_mask;
@ -2259,19 +2258,12 @@ meta_window_x11_new (MetaDisplay *display,
goto error;
}
for (tmp = display->screens; tmp != NULL; tmp = tmp->next)
if (attrs.root != screen->xroot)
{
MetaScreen *scr = tmp->data;
if (scr->xroot == attrs.root)
{
screen = tmp->data;
break;
}
meta_verbose ("Not on our screen\n");
goto error;
}
g_assert (screen);
if (is_our_xwindow (display, screen, xwindow, &attrs))
{
meta_verbose ("Not managing our own windows\n");