Compare commits
100 Commits
wip/surfac
...
wip/icons
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a0dee9883 | ||
|
|
1502d2a79f | ||
|
|
a9d8107c3d | ||
|
|
a5d2c51392 | ||
|
|
d1ea17e6a4 | ||
|
|
b37ad66e9d | ||
|
|
c1f15348a5 | ||
|
|
857561baed | ||
|
|
a44cc9ef47 | ||
|
|
d47b7ba038 | ||
|
|
f21312e2fd | ||
|
|
394af33607 | ||
|
|
7314cdac94 | ||
|
|
81025e37ea | ||
|
|
1bb9f1e333 | ||
|
|
b11c75c1c9 | ||
|
|
757b626aee | ||
|
|
fb3df5243f | ||
|
|
e34792d9f0 | ||
|
|
f397c32192 | ||
|
|
f79314d7b5 | ||
|
|
55c61259d8 | ||
|
|
5298cf0a3a | ||
|
|
f1dc1a0cbc | ||
|
|
2cf80bc647 | ||
|
|
40c15f6e2a | ||
|
|
a8849621c9 | ||
|
|
49c0be11d6 | ||
|
|
9df8e831be | ||
|
|
84c6b2a3fa | ||
|
|
06cd669ccb | ||
|
|
81eb7d9537 | ||
|
|
dd8d8e436d | ||
|
|
d6b6b363ad | ||
|
|
254e2e993c | ||
|
|
c595a9c29f | ||
|
|
dfc7f7222b | ||
|
|
ef278eb547 | ||
|
|
38e26e5cc3 | ||
|
|
9773a879c3 | ||
|
|
abd2abcde6 | ||
|
|
a8f4651c72 | ||
|
|
54df7934ea | ||
|
|
9052efb0d9 | ||
|
|
b346f98eb0 | ||
|
|
365af53797 | ||
|
|
bee59ec0e1 | ||
|
|
91384a32b4 | ||
|
|
72bd5fb814 | ||
|
|
46af3ef9f6 | ||
|
|
d417c615d5 | ||
|
|
46cbd0bf48 | ||
|
|
f3b6fead4d | ||
|
|
80de8ec643 | ||
|
|
4f7e2a9f3f | ||
|
|
701e06d55d | ||
|
|
94f39a493f | ||
|
|
ddc171220a | ||
|
|
0313b38dd6 | ||
|
|
d41fba6558 | ||
|
|
770b58b367 | ||
|
|
77838c2ca3 | ||
|
|
e56cbfbd0f | ||
|
|
a27fb19473 | ||
|
|
674bcef6da | ||
|
|
86c1c30245 | ||
|
|
283546b379 | ||
|
|
98e3e5e50f | ||
|
|
b6a0d4d368 | ||
|
|
28859c604f | ||
|
|
9e51d98f4a | ||
|
|
268a4c92ba | ||
|
|
71367e14d5 | ||
|
|
5c99eae8a9 | ||
|
|
89aa5df711 | ||
|
|
b9a5d710b7 | ||
|
|
65dd54a4db | ||
|
|
b00fa70d91 | ||
|
|
360d423faa | ||
|
|
394b44a2c2 | ||
|
|
ed6821a819 | ||
|
|
23b0f7be43 | ||
|
|
7f195aec7a | ||
|
|
da13e3d237 | ||
|
|
75184d4c55 | ||
|
|
eb75306f8a | ||
|
|
98c4b82907 | ||
|
|
640102c03b | ||
|
|
c0d791cd6e | ||
|
|
41d5e69de5 | ||
|
|
2dc7371944 | ||
|
|
ec2c3e1438 | ||
|
|
c5c3806a04 | ||
|
|
ac0c7df4a3 | ||
|
|
d85845426c | ||
|
|
060e60f2a0 | ||
|
|
26cf75d5a4 | ||
|
|
9f5087e97d | ||
|
|
45624f2edf | ||
|
|
153f843ea6 |
14
NEWS
14
NEWS
@@ -1,3 +1,17 @@
|
||||
3.11.91
|
||||
=======
|
||||
* Don't use keysym to match keybindings [Rui; #678001]
|
||||
* Fix message tray icons showing up blank (again) [Adel; #725180]
|
||||
* Improve keybinding lookups [Rui; #725588]
|
||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
|
||||
* Fix positioning of manually positioned windows [Owen; #724049]
|
||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
|
||||
#724969, #725216, #724402, #722266, #725338, #725525]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.90
|
||||
=======
|
||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
||||
|
||||
@@ -5,7 +5,7 @@ srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="mutter"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.13
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
|
||||
@@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [11])
|
||||
m4_define([mutter_micro_version], [90])
|
||||
m4_define([mutter_micro_version], [91])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -78,7 +78,7 @@ MUTTER_PC_MODULES="
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.1
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
cogl-1.0 >= 1.17.1
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
@@ -142,11 +142,6 @@ AM_GLIB_GNU_GETTEXT
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $MUTTER_LAUNCH"
|
||||
AC_CHECK_FUNCS([sd_session_get_vt])
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
|
||||
|
||||
@@ -40,19 +40,22 @@
|
||||
|
||||
<enum name="version">
|
||||
<description summary="latest protocol version">
|
||||
Use this enum to check the protocol version, and it will be updated
|
||||
automatically.
|
||||
The 'current' member of this enum gives the version of the
|
||||
protocol. Implementations can compare this to the version
|
||||
they implement using static_assert to ensure the protocol and
|
||||
implementation versions match.
|
||||
</description>
|
||||
<entry name="current" value="2" summary="Always the latest version"/>
|
||||
<entry name="current" value="3" summary="Always the latest version"/>
|
||||
</enum>
|
||||
|
||||
|
||||
<request name="use_unstable_version">
|
||||
<description summary="enable use of this unstable version">
|
||||
Use this request in order to enable use of this interface.
|
||||
|
||||
Understand and agree that one is using an unstable interface,
|
||||
that will likely change in the future, breaking the API.
|
||||
Negotiate the unstable version of the interface. This
|
||||
mechanism is in place to ensure client and server agree on the
|
||||
unstable versions of the protocol that they speak or exit
|
||||
cleanly if they don't agree. This request will go away once
|
||||
the xdg-shell protocol is stable.
|
||||
</description>
|
||||
<arg name="version" type="int"/>
|
||||
</request>
|
||||
@@ -275,113 +278,87 @@
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<event name="request_set_fullscreen">
|
||||
<description summary="server requests that the client set fullscreen">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
goes to a fullscreen state. It's the client job to call set_fullscreen
|
||||
and really trigger the fullscreen state.
|
||||
<enum name="state">
|
||||
<description summary="types of state on the surface">
|
||||
The different state values used on the surface. This is designed for
|
||||
state values like maximized, fullscreen. It is paired with the
|
||||
request_change_state event to ensure that both the client and the
|
||||
compositor setting the state can be synchronized.
|
||||
|
||||
States set in this way are double-buffered. They will get applied on
|
||||
the next commit.
|
||||
|
||||
Desktop environments may extend this enum by taking up a range of
|
||||
values and documenting the range they chose in this description.
|
||||
They are not required to document the values for the range that they
|
||||
chose. Ideally, any good extensions from a desktop environment should
|
||||
make its way into standardization into this enum.
|
||||
|
||||
The current reserved ranges are:
|
||||
|
||||
0x0000 - 0x0FFF: xdg-shell core values, documented below.
|
||||
0x1000 - 0x1FFF: GNOME
|
||||
</description>
|
||||
</event>
|
||||
<entry name="maximized" value="1" summary="the surface is maximized">
|
||||
A non-zero value indicates the surface is maximized. Otherwise,
|
||||
the surface is unmaximized.
|
||||
</entry>
|
||||
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
|
||||
A non-zero value indicates the surface is fullscreen. Otherwise,
|
||||
the surface is not fullscreen.
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<event name="request_unset_fullscreen">
|
||||
<description summary="server requests that the client unset fullscreen">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
leaves the fullscreen state. It's the client job to call
|
||||
unset_fullscreen and really leave the fullscreen state.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="set_fullscreen">
|
||||
<description summary="set the surface state as fullscreen">
|
||||
Set the surface as fullscreen.
|
||||
|
||||
After this request, the compositor should send a configure event
|
||||
informing the output size.
|
||||
|
||||
This request informs the compositor that the next attached buffer
|
||||
committed will be in a fullscreen state. The buffer size should be the
|
||||
same size as the size informed in the configure event, if the client
|
||||
doesn't want to leave any empty area.
|
||||
|
||||
In other words: the next attached buffer after set_maximized is the new
|
||||
maximized buffer. And the surface will be positioned at the maximized
|
||||
position on commit.
|
||||
|
||||
A simple way to synchronize and wait for the correct configure event is
|
||||
to use a wl_display.sync request right after the set_fullscreen
|
||||
request. When the sync callback returns, the last configure event
|
||||
received just before it will be the correct one, and should contain the
|
||||
right size for the surface to maximize.
|
||||
|
||||
Setting one state won't unset another state. Use
|
||||
xdg_surface.unset_fullscreen for unsetting it.
|
||||
<request name="request_change_state">
|
||||
<description summary="client requests to change a surface's state">
|
||||
This asks the compositor to change the state. If the compositor wants
|
||||
to change the state, it will send a change_state event with the same
|
||||
state_type, value, and serial, and the event flow continues as if it
|
||||
it was initiated by the compositor.
|
||||
|
||||
If the compositor does not want to change the state, it will send a
|
||||
change_state to the client with the old value of the state.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="an event serial">
|
||||
This serial is so the client can know which change_state event corresponds
|
||||
to which request_change_state request it sent out.
|
||||
</arg>
|
||||
</request>
|
||||
|
||||
<request name="unset_fullscreen">
|
||||
<description summary="unset the surface state as fullscreen">
|
||||
Unset the surface fullscreen state.
|
||||
|
||||
Same negotiation as set_fullscreen must be used.
|
||||
<event name="change_state">
|
||||
<description summary="compositor wants to change a surface's state">
|
||||
This event tells the client to change a surface's state. The client
|
||||
should respond with an ack_change_state request to the compositor to
|
||||
guarantee that the compositor knows that the client has seen it.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="request_set_maximized">
|
||||
<description summary="server requests that the client set maximized">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
goes to a maximized state. It's the client job to call set_maximized
|
||||
and really trigger the maximized state.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
|
||||
</event>
|
||||
|
||||
<event name="request_unset_maximized">
|
||||
<description summary="server requests that the client unset maximized">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
leaves the maximized state. It's the client job to call unset_maximized
|
||||
and really leave the maximized state.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="set_maximized">
|
||||
<description summary="set the surface state as maximized">
|
||||
Set the surface as maximized.
|
||||
|
||||
After this request, the compositor will send a configure event
|
||||
informing the output size minus panel and other MW decorations.
|
||||
|
||||
This request informs the compositor that the next attached buffer
|
||||
committed will be in a maximized state. The buffer size should be the
|
||||
same size as the size informed in the configure event, if the client
|
||||
doesn't want to leave any empty area.
|
||||
|
||||
In other words: the next attached buffer after set_maximized is the new
|
||||
maximized buffer. And the surface will be positioned at the maximized
|
||||
position on commit.
|
||||
|
||||
A simple way to synchronize and wait for the correct configure event is
|
||||
to use a wl_display.sync request right after the set_maximized request.
|
||||
When the sync callback returns, the last configure event received just
|
||||
before it will be the correct one, and should contain the right size
|
||||
for the surface to maximize.
|
||||
|
||||
Setting one state won't unset another state. Use
|
||||
xdg_surface.unset_maximized for unsetting it.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="unset_maximized">
|
||||
<description summary="unset the surface state as maximized">
|
||||
Unset the surface maximized state.
|
||||
|
||||
Same negotiation as set_maximized must be used.
|
||||
<request name="ack_change_state">
|
||||
<description summary="ack a change_state event">
|
||||
When a change_state event is received, a client should then ack it
|
||||
using the ack_change_state request to ensure that the compositor
|
||||
knows the client has seen the event.
|
||||
|
||||
By this point, the state is confirmed, and the next attach should
|
||||
contain the buffer drawn for the new state value.
|
||||
|
||||
The values here need to be the same as the values in the cooresponding
|
||||
change_state event.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="a serial to pass to change_state"/>
|
||||
</request>
|
||||
|
||||
<request name="set_minimized">
|
||||
<description summary="set the surface state as minimized">
|
||||
Set the surface minimized state.
|
||||
|
||||
Setting one state won't unset another state.
|
||||
<description summary="minimize the surface">
|
||||
Minimize the surface.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
|
||||
@@ -29,6 +29,18 @@
|
||||
<KeyListEntry name="move-to-workspace-down"
|
||||
_description="Move window one workspace down" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-left"
|
||||
_description="Move window one monitor to the left" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-right"
|
||||
_description="Move window one monitor to the right" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-up"
|
||||
_description="Move window one monitor up" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-down"
|
||||
_description="Move window one monitor down" />
|
||||
|
||||
<KeyListEntry name="switch-applications"
|
||||
_description="Switch applications"/>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter-wayland.la
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
@@ -112,8 +113,6 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/display.c \
|
||||
core/display-private.h \
|
||||
meta/display.h \
|
||||
ui/draw-workspace.c \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/edid-parse.c \
|
||||
@@ -129,8 +128,8 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/group-props.h \
|
||||
core/group.c \
|
||||
meta/group.h \
|
||||
core/iconcache.c \
|
||||
core/iconcache.h \
|
||||
core/icons.c \
|
||||
core/icons.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -184,14 +183,13 @@ libmutter_wayland_la_SOURCES = \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
ui/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
ui/tabpopup.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme.c \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "util-private.h"
|
||||
#include "frame.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
@@ -435,45 +436,6 @@ begin_modal_x11 (MetaScreen *screen,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
begin_modal_wayland (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
|
||||
goto fail;
|
||||
|
||||
pointer_grabbed = TRUE;
|
||||
}
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard,
|
||||
timestamp))
|
||||
goto fail;
|
||||
|
||||
keyboard_grabbed = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
if (pointer_grabbed)
|
||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
||||
if (keyboard_grabbed)
|
||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard, timestamp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
@@ -492,7 +454,7 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
return FALSE;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
ok = begin_modal_wayland (screen, plugin, options, timestamp);
|
||||
ok = TRUE;
|
||||
else
|
||||
ok = begin_modal_x11 (screen, plugin, options, timestamp);
|
||||
if (!ok)
|
||||
@@ -520,15 +482,7 @@ meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
|
||||
g_return_if_fail (compositor->modal_plugin == plugin);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
@@ -940,6 +894,66 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
meta_window_actor_update_opacity (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_update_surface (window_actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_op_is_clicking (MetaGrabOp grab_op)
|
||||
{
|
||||
switch (grab_op)
|
||||
{
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
case META_GRAB_OP_CLICKING_MENU:
|
||||
case META_GRAB_OP_CLICKING_SHADE:
|
||||
case META_GRAB_OP_CLICKING_UNSHADE:
|
||||
case META_GRAB_OP_CLICKING_ABOVE:
|
||||
case META_GRAB_OP_CLICKING_UNABOVE:
|
||||
case META_GRAB_OP_CLICKING_STICK:
|
||||
case META_GRAB_OP_CLICKING_UNSTICK:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_is_passive_button_grab (MetaDisplay *display,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
/* see display.c for which events are passive button
|
||||
grabs (meta_display_grab_window_buttons() and
|
||||
meta_display_handle_events())
|
||||
we need to filter them here because normally they
|
||||
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
||||
but we want to redirect them to clutter
|
||||
*/
|
||||
|
||||
if (device_event->evtype != XI_ButtonPress)
|
||||
return FALSE;
|
||||
|
||||
if (display->window_grab_modifiers == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
||||
display->window_grab_modifiers)
|
||||
return FALSE;
|
||||
|
||||
return device_event->detail < 4;
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
@@ -951,6 +965,7 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (info->screen);
|
||||
@@ -959,24 +974,30 @@ maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
event->xcookie.extension == display->xinput_opcode)
|
||||
{
|
||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
||||
let GTK+ handle it without mangling */
|
||||
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
||||
(grab_op_is_clicking (display->grab_op) ||
|
||||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
||||
break;
|
||||
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
||||
* it as-is without mangling. */
|
||||
if (meta_ui_window_is_widget (info->screen->ui, device_event->event))
|
||||
break;
|
||||
|
||||
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
}
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -996,6 +1017,12 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaScreen *screen = display->screens->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
|
||||
{
|
||||
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
|
||||
@@ -1005,43 +1032,13 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (window)
|
||||
if (!meta_is_wayland_compositor ())
|
||||
maybe_spoof_event_as_stage_event (info, window, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
l = meta_display_get_screens (compositor->display);
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaScreen *screen = l->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
maybe_spoof_event_as_stage_event (info, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/screen.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
@@ -576,8 +577,18 @@ static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
|
||||
|
||||
return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
|
||||
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
|
||||
return NULL;
|
||||
|
||||
while (parent && !META_IS_WINDOW_ACTOR (parent))
|
||||
parent = clutter_actor_get_parent (parent);
|
||||
|
||||
if (parent && clutter_actor_has_mapped_clones (parent))
|
||||
return NULL;
|
||||
|
||||
return priv->unobscured_region;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
@@ -97,6 +98,14 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
|
||||
return priv->surface->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
{
|
||||
@@ -110,6 +119,8 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -387,6 +387,14 @@ meta_surface_actor_x11_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_x11_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor));
|
||||
|
||||
return priv->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
{
|
||||
@@ -403,6 +411,8 @@ meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_x11_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -456,6 +466,7 @@ meta_surface_actor_x11_new (MetaWindow *window)
|
||||
priv->unredirected = FALSE;
|
||||
sync_unredirected (self);
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
@@ -26,8 +25,8 @@ struct _MetaSurfaceActorPrivate
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* Freeze/thaw accounting */
|
||||
guint freeze_count;
|
||||
guint needs_damage_all : 1;
|
||||
guint frozen : 1;
|
||||
};
|
||||
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
@@ -223,7 +222,7 @@ static gboolean
|
||||
is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return (priv->freeze_count > 0);
|
||||
return priv->frozen;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -274,31 +273,19 @@ meta_surface_actor_is_visible (MetaSurfaceActor *self)
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_freeze (MetaSurfaceActor *self)
|
||||
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
||||
gboolean frozen)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
priv->freeze_count ++;
|
||||
}
|
||||
priv->frozen = frozen;
|
||||
|
||||
void
|
||||
meta_surface_actor_thaw (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->freeze_count == 0)
|
||||
if (!frozen && priv->needs_damage_all)
|
||||
{
|
||||
g_critical ("Error in freeze/thaw accounting.");
|
||||
return;
|
||||
}
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
|
||||
priv->freeze_count --;
|
||||
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
if (priv->needs_damage_all)
|
||||
{
|
||||
meta_surface_actor_process_damage (self, 0, 0,
|
||||
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
|
||||
@@ -306,12 +293,6 @@ meta_surface_actor_thaw (MetaSurfaceActor *self)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
return is_frozen (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
|
||||
{
|
||||
@@ -330,3 +311,9 @@ meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_surface_actor_get_window (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -35,6 +36,8 @@ struct _MetaSurfaceActorClass
|
||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||
|
||||
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActor
|
||||
@@ -50,6 +53,7 @@ cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *clip);
|
||||
|
||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
|
||||
|
||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
@@ -69,9 +73,8 @@ void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
|
||||
|
||||
void meta_surface_actor_freeze (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_thaw (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
|
||||
gboolean frozen);
|
||||
|
||||
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <meta-wayland-private.h>
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include "meta-surface-actor.h"
|
||||
@@ -63,5 +60,6 @@ void meta_window_actor_effect_completed (MetaWindowActor *actor,
|
||||
gulong event);
|
||||
|
||||
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
|
||||
void meta_window_actor_update_surface (MetaWindowActor *self);
|
||||
|
||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-texture-rectangle.h"
|
||||
#include "region-utils.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "monitor-private.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-x11.h"
|
||||
@@ -84,6 +84,7 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
/* List of FrameData for recent frames */
|
||||
GList *frames;
|
||||
guint freeze_count;
|
||||
|
||||
guint visible : 1;
|
||||
guint disposed : 1;
|
||||
@@ -253,7 +254,15 @@ static gboolean
|
||||
is_argb32 (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
return meta_surface_actor_is_argb32 (priv->surface);
|
||||
|
||||
/* assume we're argb until we get the window (because
|
||||
in practice we're drawing nothing, so we're fully
|
||||
transparent)
|
||||
*/
|
||||
if (priv->surface)
|
||||
return meta_surface_actor_is_argb32 (priv->surface);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -269,14 +278,19 @@ static gboolean
|
||||
is_frozen (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
return meta_surface_actor_is_frozen (priv->surface);
|
||||
|
||||
return priv->surface == NULL || priv->freeze_count > 0;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_freeze (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
meta_surface_actor_freeze (priv->surface);
|
||||
|
||||
if (priv->freeze_count == 0 && priv->surface)
|
||||
meta_surface_actor_set_frozen (priv->surface, TRUE);
|
||||
|
||||
priv->freeze_count ++;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -284,11 +298,16 @@ meta_window_actor_thaw (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
meta_surface_actor_thaw (priv->surface);
|
||||
if (priv->freeze_count <= 0)
|
||||
g_error ("Error in freeze/thaw accounting");
|
||||
|
||||
if (is_frozen (self))
|
||||
priv->freeze_count--;
|
||||
if (priv->freeze_count > 0)
|
||||
return;
|
||||
|
||||
if (priv->surface)
|
||||
meta_surface_actor_set_frozen (priv->surface, FALSE);
|
||||
|
||||
/* We sometimes ignore moves and resizes on frozen windows */
|
||||
meta_window_actor_sync_actor_geometry (self, FALSE);
|
||||
|
||||
@@ -326,14 +345,13 @@ set_surface (MetaWindowActor *self,
|
||||
|
||||
/* If the previous surface actor was frozen, start out
|
||||
* frozen as well... */
|
||||
if (priv->updates_frozen)
|
||||
meta_surface_actor_freeze (priv->surface);
|
||||
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
|
||||
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_window_actor_update_surface (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
@@ -342,8 +360,10 @@ meta_window_actor_update_surface (MetaWindowActor *self)
|
||||
|
||||
if (window->surface)
|
||||
surface_actor = window->surface->surface_actor;
|
||||
else
|
||||
else if (!meta_is_wayland_compositor ())
|
||||
surface_actor = meta_surface_actor_x11_new (window);
|
||||
else
|
||||
surface_actor = NULL;
|
||||
|
||||
set_surface (self, surface_actor);
|
||||
}
|
||||
@@ -650,8 +670,11 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
|
||||
|
||||
meta_window_actor_get_shape_bounds (self, &bounds);
|
||||
|
||||
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
|
||||
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
|
||||
if (priv->surface)
|
||||
{
|
||||
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
|
||||
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
|
||||
}
|
||||
|
||||
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
|
||||
{
|
||||
@@ -762,21 +785,26 @@ meta_window_actor_get_meta_window (MetaWindowActor *self)
|
||||
* meta_window_actor_get_texture:
|
||||
* @self: a #MetaWindowActor
|
||||
*
|
||||
* Gets the ClutterActor that is used to display the contents of the window
|
||||
* Gets the ClutterActor that is used to display the contents of the window,
|
||||
* or NULL if no texture is shown yet, because the window is not mapped.
|
||||
*
|
||||
* Return value: (transfer none): the #ClutterActor for the contents
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_window_actor_get_texture (MetaWindowActor *self)
|
||||
{
|
||||
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
|
||||
if (self->priv->surface)
|
||||
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_get_surface:
|
||||
* @self: a #MetaWindowActor
|
||||
*
|
||||
* Gets the MetaSurfaceActor that draws the content of this window
|
||||
* Gets the MetaSurfaceActor that draws the content of this window,
|
||||
* or NULL if there is no surface yet associated with this window.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaSurfaceActor for the contents
|
||||
*/
|
||||
@@ -875,7 +903,12 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
|
||||
if (!priv->repaint_scheduled)
|
||||
{
|
||||
gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface);
|
||||
gboolean is_obscured;
|
||||
|
||||
if (priv->surface)
|
||||
is_obscured = meta_surface_actor_is_obscured (priv->surface);
|
||||
else
|
||||
is_obscured = FALSE;
|
||||
|
||||
/* A frame was marked by the client without actually doing any
|
||||
* damage or any unobscured, or while we had the window frozen
|
||||
@@ -891,9 +924,12 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
|
||||
priv->repaint_scheduled = TRUE;
|
||||
if (priv->surface)
|
||||
{
|
||||
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
|
||||
priv->repaint_scheduled = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1066,7 +1102,10 @@ gboolean
|
||||
meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
if (priv->surface)
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1074,6 +1113,8 @@ meta_window_actor_set_unredirected (MetaWindowActor *self,
|
||||
gboolean unredirected)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
g_assert(priv->surface); /* because otherwise should_unredirect() is FALSE */
|
||||
meta_surface_actor_set_unredirected (priv->surface, unredirected);
|
||||
}
|
||||
|
||||
@@ -1430,6 +1471,7 @@ meta_window_actor_cull_out (MetaCullable *cullable,
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
||||
|
||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||
meta_window_actor_set_clip_region_beneath (self, clip_region);
|
||||
}
|
||||
|
||||
@@ -1519,11 +1561,12 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
meta_surface_actor_process_damage (priv->surface,
|
||||
event->area.x,
|
||||
event->area.y,
|
||||
event->area.width,
|
||||
event->area.height);
|
||||
if (priv->surface)
|
||||
meta_surface_actor_process_damage (priv->surface,
|
||||
event->area.x,
|
||||
event->area.y,
|
||||
event->area.width,
|
||||
event->area.height);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1671,22 +1714,25 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
||||
cogl_object_unref (mask_texture);
|
||||
if (mask_texture)
|
||||
cogl_object_unref (mask_texture);
|
||||
|
||||
g_free (mask_data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
meta_window_actor_update_shape_region (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
cairo_region_t *region = NULL;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
|
||||
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
|
||||
{
|
||||
region = cairo_region_copy (priv->window->shape_region);
|
||||
cairo_region_translate (region, client_area->x, client_area->y);
|
||||
cairo_region_translate (region, client_area.x, client_area.y);
|
||||
}
|
||||
else if (priv->window->shape_region != NULL)
|
||||
{
|
||||
@@ -1697,11 +1743,11 @@ meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||
/* If we don't have a shape on the server, that means that
|
||||
* we have an implicit shape of one rectangle covering the
|
||||
* entire window. */
|
||||
region = cairo_region_create_rectangle (client_area);
|
||||
region = cairo_region_create_rectangle (&client_area);
|
||||
}
|
||||
|
||||
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
|
||||
build_and_scan_frame_mask (self, client_area, region);
|
||||
build_and_scan_frame_mask (self, &client_area, region);
|
||||
|
||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||
priv->shape_region = region;
|
||||
@@ -1712,34 +1758,43 @@ meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
cairo_region_t *region = NULL;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
if (priv->window->frame != NULL && priv->window->input_region != NULL)
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
|
||||
if (priv->window->frame != NULL)
|
||||
{
|
||||
region = meta_frame_get_frame_bounds (priv->window->frame);
|
||||
|
||||
cairo_region_subtract_rectangle (region, client_area);
|
||||
|
||||
/* input_region is in client window coordinates, so translate the
|
||||
* input region into that coordinate system and back */
|
||||
cairo_region_translate (region, -client_area->x, -client_area->y);
|
||||
cairo_region_union (region, priv->window->input_region);
|
||||
cairo_region_translate (region, client_area->x, client_area->y);
|
||||
cairo_region_translate (region, -client_area.x, -client_area.y);
|
||||
cairo_region_union_rectangle (region, &client_area);
|
||||
cairo_region_translate (region, client_area.x, client_area.y);
|
||||
}
|
||||
else if (priv->window->input_region != NULL)
|
||||
else if (priv->window->shape_region != NULL ||
|
||||
priv->window->input_region != NULL)
|
||||
{
|
||||
region = cairo_region_reference (priv->window->input_region);
|
||||
if (priv->window->shape_region != NULL)
|
||||
{
|
||||
region = cairo_region_copy (priv->window->shape_region);
|
||||
|
||||
if (priv->window->input_region != NULL)
|
||||
cairo_region_intersect (region, priv->window->input_region);
|
||||
}
|
||||
else
|
||||
region = cairo_region_reference (priv->window->input_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we don't have a shape on the server, that means that
|
||||
* we have an implicit shape of one rectangle covering the
|
||||
* entire window. */
|
||||
region = cairo_region_create_rectangle (client_area);
|
||||
region = cairo_region_create_rectangle (&client_area);
|
||||
}
|
||||
|
||||
meta_surface_actor_set_input_region (priv->surface, region);
|
||||
@@ -1755,9 +1810,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
|
||||
if (argb32 && priv->window->opaque_region != NULL)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
|
||||
/* The opaque region is defined to be a part of the
|
||||
* window which ARGB32 will always paint with opaque
|
||||
@@ -1770,7 +1825,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
* case, graphical glitches will occur.
|
||||
*/
|
||||
opaque_region = cairo_region_copy (priv->window->opaque_region);
|
||||
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
|
||||
cairo_region_translate (opaque_region, client_area.x, client_area.y);
|
||||
cairo_region_intersect (opaque_region, priv->shape_region);
|
||||
}
|
||||
else if (argb32)
|
||||
@@ -1786,27 +1841,15 @@ static void
|
||||
check_needs_reshape (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaFrameBorders borders;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
if (!priv->needs_reshape)
|
||||
return;
|
||||
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
|
||||
client_area.x = borders.total.left;
|
||||
client_area.y = borders.total.top;
|
||||
client_area.width = priv->window->rect.width;
|
||||
if (priv->window->shaded)
|
||||
client_area.height = 0;
|
||||
else
|
||||
client_area.height = priv->window->rect.height;
|
||||
|
||||
meta_window_actor_update_shape_region (self, &client_area);
|
||||
meta_window_actor_update_shape_region (self);
|
||||
|
||||
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
meta_window_actor_update_input_region (self, &client_area);
|
||||
meta_window_actor_update_input_region (self);
|
||||
meta_window_actor_update_opaque_region (self);
|
||||
}
|
||||
|
||||
@@ -2026,7 +2069,8 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (self->priv->surface), window->opacity);
|
||||
if (priv->surface)
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -425,8 +425,9 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
window->decorated &&
|
||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
@@ -491,12 +492,17 @@ place_window_if_needed(MetaWindow *window,
|
||||
!window->minimized &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
MetaRectangle orig_rect;
|
||||
MetaRectangle placed_rect;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
|
||||
meta_window_get_frame_rect (window, &placed_rect);
|
||||
meta_window_place (window, info->orig.x, info->orig.y,
|
||||
|
||||
orig_rect = info->orig;
|
||||
extend_by_frame (window, &orig_rect);
|
||||
|
||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
|
||||
@@ -736,31 +736,6 @@ meta_core_increment_event_serial (Display *xdisplay)
|
||||
meta_display_increment_event_serial (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_invalidate_default_icons (void)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
GSList *windows;
|
||||
GSList *l;
|
||||
|
||||
if (display == NULL)
|
||||
return; /* We can validly be called before the display is opened. */
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
for (l = windows; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWindow *window = (MetaWindow*)l->data;
|
||||
|
||||
if (window->icon_cache.origin == USING_FALLBACK_ICON)
|
||||
{
|
||||
meta_icon_cache_free (&(window->icon_cache));
|
||||
meta_window_update_icon_now (window);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_add_old_event_mask (Display *xdisplay,
|
||||
Window xwindow,
|
||||
|
||||
@@ -199,8 +199,6 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
*/
|
||||
void meta_core_increment_event_serial (Display *display);
|
||||
|
||||
void meta_invalidate_default_icons (void);
|
||||
|
||||
void meta_core_add_old_event_mask (Display *xdisplay,
|
||||
Window xwindow,
|
||||
XIEventMask *mask);
|
||||
|
||||
@@ -215,7 +215,6 @@ struct _MetaDisplay
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
@@ -233,8 +232,8 @@ struct _MetaDisplay
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
/* Keybindings stuff */
|
||||
MetaKeyBinding *key_bindings;
|
||||
int n_key_bindings;
|
||||
GHashTable *key_bindings;
|
||||
GHashTable *key_bindings_index;
|
||||
int min_keycode;
|
||||
int max_keycode;
|
||||
KeySym *keymap;
|
||||
|
||||
@@ -75,14 +75,6 @@
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
|
||||
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
|
||||
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
|
||||
g == META_GRAB_OP_KEYBOARD_TABBING_GROUP || \
|
||||
g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \
|
||||
g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \
|
||||
g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP)
|
||||
|
||||
/*
|
||||
* SECTION:pings
|
||||
*
|
||||
@@ -1303,10 +1295,6 @@ meta_get_display (void)
|
||||
return the_display;
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static gboolean dump_events = TRUE;
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
grab_op_is_mouse_only (MetaGrabOp op)
|
||||
{
|
||||
@@ -1375,13 +1363,6 @@ grab_op_is_keyboard (MetaGrabOp op)
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING_GROUP:
|
||||
case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL:
|
||||
case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK:
|
||||
case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP:
|
||||
case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING:
|
||||
case META_GRAB_OP_COMPOSITOR:
|
||||
return TRUE;
|
||||
|
||||
@@ -1433,6 +1414,20 @@ meta_grab_op_is_moving (MetaGrabOp op)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_op_should_block_mouse_events (MetaGrabOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case META_GRAB_OP_WAYLAND_CLIENT:
|
||||
case META_GRAB_OP_COMPOSITOR:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_xserver_time_is_before:
|
||||
* @display: a #MetaDisplay
|
||||
@@ -1682,14 +1677,20 @@ get_window_for_event (MetaDisplay *display,
|
||||
if (display->grab_op != META_GRAB_OP_NONE)
|
||||
return display->grab_window;
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (source))
|
||||
/* Always use the key focused window for key events. */
|
||||
switch (event->type)
|
||||
{
|
||||
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (source));
|
||||
g_assert (surface != NULL);
|
||||
return surface->window;
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
return display->focus_window;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
if (META_IS_SURFACE_ACTOR (source))
|
||||
return meta_surface_actor_get_window (META_SURFACE_ACTOR (source));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1785,19 +1786,9 @@ update_focus_window (MetaDisplay *display,
|
||||
|
||||
if (display->focus_window)
|
||||
{
|
||||
ClutterActor *window_actor;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
|
||||
display->focus_window->desc, serial);
|
||||
meta_window_set_focused_internal (display->focus_window, TRUE);
|
||||
|
||||
/* XXX -- this is sort of a layer violation, but because we
|
||||
* rely on the compositor for event delivery anyway, I don't
|
||||
* think it's too bad... */
|
||||
|
||||
window_actor = CLUTTER_ACTOR (display->focus_window->compositor_private);
|
||||
if (window_actor)
|
||||
clutter_actor_grab_key_focus (window_actor);
|
||||
}
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
|
||||
@@ -2040,9 +2031,6 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
gboolean bypass_clutter = FALSE, bypass_wayland = FALSE;
|
||||
MetaWaylandCompositor *compositor = NULL;
|
||||
|
||||
/* XXX -- we need to fill this in properly at some point... */
|
||||
gboolean frame_was_receiver = FALSE;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
@@ -2076,7 +2064,7 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
@@ -2094,79 +2082,76 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
(display->grab_window ?
|
||||
display->grab_window->desc :
|
||||
"none"));
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Syncing to old stack positions.\n");
|
||||
|
||||
/* XXX: I'm not sure if this is the right thing to do.
|
||||
The pre-Wayland code was only calling
|
||||
meta_stack_set_positions if the modified window was a
|
||||
root window */
|
||||
if (event->any.source == CLUTTER_ACTOR (event->any.stage) && window && window->screen)
|
||||
meta_stack_set_positions (window->screen->stack,
|
||||
display->grab_old_window_stacking);
|
||||
}
|
||||
meta_display_end_grab_op (display, event->any.time);
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
gboolean begin_move = FALSE;
|
||||
ClutterModifierType grab_mask;
|
||||
gboolean unmodified;
|
||||
gboolean fully_modified;
|
||||
|
||||
grab_mask = display->window_grab_modifiers;
|
||||
if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
|
||||
grab_mask |= CLUTTER_CONTROL_MASK;
|
||||
|
||||
/* Two possible sources of an unmodified event; one is a
|
||||
* client that's letting button presses pass through to the
|
||||
* frame, the other is our focus_window_grab on unmodified
|
||||
* button 1. So for all such events we focus the window.
|
||||
/* We have three passive button grabs:
|
||||
* - on any button, without modifiers => focuses and maybe raises the window
|
||||
* - on resize button, with modifiers => start an interactive resizing
|
||||
* (normally <Super>middle)
|
||||
* - on move button, with modifiers => start an interactive move
|
||||
* (normally <Super>left)
|
||||
* - on menu button, with modifiers => show the window menu
|
||||
* (normally <Super>right)
|
||||
*
|
||||
* We may get here because we actually have a button
|
||||
* grab on the window, or because we're a wayland
|
||||
* compositor and thus we see all the events, so we
|
||||
* need to check if the event is interesting.
|
||||
* We want an event that is not modified, for a window
|
||||
* that has (or would have, the wayland case) the
|
||||
* button grab active.
|
||||
*
|
||||
* We may have other events on the window, for example
|
||||
* a click on a frame button, but that's not for us to
|
||||
* care about. Just let the event through.
|
||||
*/
|
||||
unmodified = (event->button.modifier_state & grab_mask) == 0;
|
||||
fully_modified = grab_mask && (event->button.modifier_state & grab_mask) == grab_mask;
|
||||
|
||||
if (unmodified ||
|
||||
event->button.button == 1)
|
||||
if (unmodified && window && window->have_focus_click_grab)
|
||||
{
|
||||
/* don't focus if frame received, will be lowered in
|
||||
* frames.c or special-cased if the click was on a
|
||||
* minimize/close button.
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Not raising window on click due to don't-raise-on-click option\n");
|
||||
|
||||
/* Don't focus panels--they must explicitly request focus.
|
||||
* See bug 160470
|
||||
*/
|
||||
if (!frame_was_receiver)
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Not raising window on click due to don't-raise-on-click option\n");
|
||||
|
||||
/* Don't focus panels--they must explicitly request focus.
|
||||
* See bug 160470
|
||||
*/
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s due to unmodified button %u press (display.c)\n",
|
||||
window->desc, event->button.button);
|
||||
meta_window_focus (window, event->any.time);
|
||||
}
|
||||
else
|
||||
/* However, do allow terminals to lose focus due to new
|
||||
* window mappings after the user clicks on a panel.
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s due to unmodified button %u press (display.c)\n",
|
||||
window->desc, event->button.button);
|
||||
meta_window_focus (window, event->any.time);
|
||||
}
|
||||
else
|
||||
/* However, do allow terminals to lose focus due to new
|
||||
* window mappings after the user clicks on a panel.
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
|
||||
/* you can move on alt-click but not on
|
||||
* the click-to-focus
|
||||
*/
|
||||
if (!unmodified)
|
||||
begin_move = TRUE;
|
||||
meta_verbose ("Allowing events time %u\n",
|
||||
(unsigned int)event->button.time);
|
||||
|
||||
XIAllowEvents (display->xdisplay, clutter_input_device_get_device_id (event->button.device),
|
||||
XIReplayDevice, event->button.time);
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
else if (!unmodified && ((int) event->button.button == meta_prefs_get_mouse_button_resize ()))
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ())
|
||||
{
|
||||
if (window->has_resize_func)
|
||||
{
|
||||
@@ -2214,8 +2199,10 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if ((int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
@@ -2227,27 +2214,29 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
else if (fully_modified && (int) event->button.button == 1)
|
||||
{
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
FALSE,
|
||||
event->button.button,
|
||||
0,
|
||||
event->any.time,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
if (window->has_move_func)
|
||||
{
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
FALSE,
|
||||
event->button.button,
|
||||
0,
|
||||
event->any.time,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
@@ -2261,7 +2250,7 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
}
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
break;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
@@ -2295,6 +2284,10 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
bypass_wayland = TRUE;
|
||||
|
||||
/* If a Wayland client has a grab, don't pass that through to Clutter */
|
||||
if (display->grab_op == META_GRAB_OP_WAYLAND_CLIENT)
|
||||
bypass_clutter = TRUE;
|
||||
|
||||
if (compositor && !bypass_wayland)
|
||||
{
|
||||
if (meta_wayland_compositor_handle_event (compositor, event))
|
||||
@@ -2309,11 +2302,10 @@ handle_input_xevent (MetaDisplay *display,
|
||||
XIEvent *input_event,
|
||||
gulong serial)
|
||||
{
|
||||
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
|
||||
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
||||
Window modified;
|
||||
MetaWindow *window;
|
||||
gboolean frame_was_receiver;
|
||||
MetaScreen *screen;
|
||||
|
||||
if (input_event == NULL)
|
||||
return FALSE;
|
||||
@@ -2321,242 +2313,8 @@ handle_input_xevent (MetaDisplay *display,
|
||||
modified = xievent_get_modified_window (display, input_event);
|
||||
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
|
||||
|
||||
frame_was_receiver = FALSE;
|
||||
if (window &&
|
||||
window->frame &&
|
||||
modified == window->frame->xwindow)
|
||||
{
|
||||
/* Note that if the frame and the client both have an
|
||||
* XGrabButton (as is normal with our setup), the event
|
||||
* goes to the frame.
|
||||
*/
|
||||
frame_was_receiver = TRUE;
|
||||
meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
|
||||
window->desc);
|
||||
}
|
||||
|
||||
if (window && !window->override_redirect &&
|
||||
(input_event->evtype == XI_KeyPress || input_event->evtype == XI_ButtonPress))
|
||||
{
|
||||
if (CurrentTime == display->current_time)
|
||||
{
|
||||
/* We can't use missing (i.e. invalid) timestamps to set user time,
|
||||
* nor do we want to use them to sanity check other timestamps.
|
||||
* See bug 313490 for more details.
|
||||
*/
|
||||
meta_warning ("Event has no timestamp! You may be using a broken "
|
||||
"program such as xse. Please ask the authors of that "
|
||||
"program to fix it.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_set_user_time (window, display->current_time);
|
||||
sanity_check_timestamps (display, display->current_time);
|
||||
}
|
||||
}
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_ButtonPress:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
|
||||
if (device_event->detail == 4 || device_event->detail == 5)
|
||||
/* Scrollwheel event, do nothing and deliver event to compositor below */
|
||||
break;
|
||||
|
||||
if ((window &&
|
||||
meta_grab_op_is_mouse (display->grab_op) &&
|
||||
(device_event->mods.effective & display->window_grab_modifiers) &&
|
||||
display->grab_button != device_event->detail &&
|
||||
display->grab_window == window) ||
|
||||
grab_op_is_keyboard (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ending grab op %u on window %s due to button press\n",
|
||||
display->grab_op,
|
||||
(display->grab_window ?
|
||||
display->grab_window->desc :
|
||||
"none"));
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
MetaScreen *screen;
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Syncing to old stack positions.\n");
|
||||
screen =
|
||||
meta_display_screen_for_root (display, device_event->event);
|
||||
|
||||
if (screen!=NULL)
|
||||
meta_stack_set_positions (screen->stack,
|
||||
display->grab_old_window_stacking);
|
||||
}
|
||||
meta_display_end_grab_op (display,
|
||||
device_event->time);
|
||||
}
|
||||
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
gboolean begin_move = FALSE;
|
||||
unsigned int grab_mask;
|
||||
gboolean unmodified;
|
||||
|
||||
grab_mask = display->window_grab_modifiers;
|
||||
if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
|
||||
grab_mask |= ControlMask;
|
||||
|
||||
/* Two possible sources of an unmodified event; one is a
|
||||
* client that's letting button presses pass through to the
|
||||
* frame, the other is our focus_window_grab on unmodified
|
||||
* button 1. So for all such events we focus the window.
|
||||
*/
|
||||
unmodified = (device_event->mods.effective & grab_mask) == 0;
|
||||
|
||||
if (unmodified ||
|
||||
device_event->detail == 1)
|
||||
{
|
||||
/* don't focus if frame received, will be lowered in
|
||||
* frames.c or special-cased if the click was on a
|
||||
* minimize/close button.
|
||||
*/
|
||||
if (!frame_was_receiver)
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Not raising window on click due to don't-raise-on-click option\n");
|
||||
|
||||
/* Don't focus panels--they must explicitly request focus.
|
||||
* See bug 160470
|
||||
*/
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s due to unmodified button %u press (display.c)\n",
|
||||
window->desc, device_event->detail);
|
||||
meta_window_focus (window, device_event->time);
|
||||
}
|
||||
else
|
||||
/* However, do allow terminals to lose focus due to new
|
||||
* window mappings after the user clicks on a panel.
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
}
|
||||
|
||||
/* you can move on alt-click but not on
|
||||
* the click-to-focus
|
||||
*/
|
||||
if (!unmodified)
|
||||
begin_move = TRUE;
|
||||
}
|
||||
else if (!unmodified && device_event->detail == meta_prefs_get_mouse_button_resize())
|
||||
{
|
||||
if (window->has_resize_func)
|
||||
{
|
||||
gboolean north, south;
|
||||
gboolean west, east;
|
||||
MetaRectangle frame_rect;
|
||||
MetaGrabOp op;
|
||||
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
west = device_event->root_x < (frame_rect.x + 1 * frame_rect.width / 3);
|
||||
east = device_event->root_x > (frame_rect.x + 2 * frame_rect.width / 3);
|
||||
north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
|
||||
south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
|
||||
|
||||
if (north && west)
|
||||
op = META_GRAB_OP_RESIZING_NW;
|
||||
else if (north && east)
|
||||
op = META_GRAB_OP_RESIZING_NE;
|
||||
else if (south && west)
|
||||
op = META_GRAB_OP_RESIZING_SW;
|
||||
else if (south && east)
|
||||
op = META_GRAB_OP_RESIZING_SE;
|
||||
else if (north)
|
||||
op = META_GRAB_OP_RESIZING_N;
|
||||
else if (west)
|
||||
op = META_GRAB_OP_RESIZING_W;
|
||||
else if (east)
|
||||
op = META_GRAB_OP_RESIZING_E;
|
||||
else if (south)
|
||||
op = META_GRAB_OP_RESIZING_S;
|
||||
else /* Middle region is no-op to avoid user triggering wrong action */
|
||||
op = META_GRAB_OP_NONE;
|
||||
|
||||
if (op != META_GRAB_OP_NONE)
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
op,
|
||||
TRUE,
|
||||
FALSE,
|
||||
device_event->detail,
|
||||
0,
|
||||
device_event->time,
|
||||
device_event->root_x,
|
||||
device_event->root_y);
|
||||
}
|
||||
}
|
||||
else if (device_event->detail == meta_prefs_get_mouse_button_menu())
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
meta_window_show_menu (window,
|
||||
device_event->root_x,
|
||||
device_event->root_y,
|
||||
device_event->detail,
|
||||
device_event->time);
|
||||
}
|
||||
|
||||
if (!frame_was_receiver && unmodified)
|
||||
{
|
||||
/* This is from our synchronous grab since
|
||||
* it has no modifiers and was on the client window
|
||||
*/
|
||||
|
||||
meta_verbose ("Allowing events time %u\n",
|
||||
(unsigned int)device_event->time);
|
||||
|
||||
XIAllowEvents (display->xdisplay, device_event->deviceid,
|
||||
XIReplayDevice, device_event->time);
|
||||
}
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
{
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
FALSE,
|
||||
device_event->detail,
|
||||
0,
|
||||
device_event->time,
|
||||
device_event->root_x,
|
||||
device_event->root_y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_mouse (display->grab_op))
|
||||
meta_window_handle_mouse_grab_op_xevent (window, device_event);
|
||||
break;
|
||||
case XI_Motion:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_mouse (display->grab_op))
|
||||
meta_window_handle_mouse_grab_op_xevent (window, device_event);
|
||||
break;
|
||||
case XI_Enter:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
@@ -2612,12 +2370,11 @@ handle_input_xevent (MetaDisplay *display,
|
||||
if (!window)
|
||||
{
|
||||
/* Check if the window is a root window. */
|
||||
MetaScreen *screen =
|
||||
meta_display_screen_for_root(display,
|
||||
enter_event->event);
|
||||
if (screen == NULL)
|
||||
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)
|
||||
{
|
||||
@@ -2643,7 +2400,9 @@ handle_input_xevent (MetaDisplay *display,
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
/* Don't send FocusIn / FocusOut to Clutter */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -3229,9 +2988,8 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
MetaMonitorManager *monitor;
|
||||
MetaScreen *screen;
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
if (dump_events)
|
||||
meta_spew_event (display, event);
|
||||
#if 0
|
||||
meta_spew_event (display, event);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
@@ -3507,8 +3265,7 @@ event_get_time (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
const char*
|
||||
G_GNUC_UNUSED const char*
|
||||
meta_event_detail_to_string (int d)
|
||||
{
|
||||
const char *detail = "???";
|
||||
@@ -3544,10 +3301,8 @@ meta_event_detail_to_string (int d)
|
||||
|
||||
return detail;
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
const char*
|
||||
G_GNUC_UNUSED const char*
|
||||
meta_event_mode_to_string (int m)
|
||||
{
|
||||
const char *mode = "???";
|
||||
@@ -3569,10 +3324,8 @@ meta_event_mode_to_string (int m)
|
||||
|
||||
return mode;
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static const char*
|
||||
G_GNUC_UNUSED static const char*
|
||||
stack_mode_to_string (int mode)
|
||||
{
|
||||
switch (mode)
|
||||
@@ -3591,11 +3344,9 @@ stack_mode_to_string (int mode)
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static gint64
|
||||
G_GNUC_UNUSED static gint64
|
||||
sync_value_to_64 (const XSyncValue *value)
|
||||
{
|
||||
gint64 v;
|
||||
@@ -3605,10 +3356,8 @@ sync_value_to_64 (const XSyncValue *value)
|
||||
|
||||
return v;
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static const char*
|
||||
G_GNUC_UNUSED static const char*
|
||||
alarm_state_to_string (XSyncAlarmState state)
|
||||
{
|
||||
switch (state)
|
||||
@@ -3623,12 +3372,9 @@ alarm_state_to_string (XSyncAlarmState state)
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void
|
||||
G_GNUC_UNUSED static void
|
||||
meta_spew_xi2_event (MetaDisplay *display,
|
||||
XIEvent *input_event,
|
||||
const char **name_p,
|
||||
@@ -3637,26 +3383,10 @@ meta_spew_xi2_event (MetaDisplay *display,
|
||||
const char *name = NULL;
|
||||
char *extra = NULL;
|
||||
|
||||
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
|
||||
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
name = "XI_Motion";
|
||||
break;
|
||||
case XI_ButtonPress:
|
||||
name = "XI_ButtonPress";
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
name = "XI_ButtonRelease";
|
||||
break;
|
||||
case XI_KeyPress:
|
||||
name = "XI_KeyPress";
|
||||
break;
|
||||
case XI_KeyRelease:
|
||||
name = "XI_KeyRelease";
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
name = "XI_FocusIn";
|
||||
break;
|
||||
@@ -3681,34 +3411,6 @@ meta_spew_xi2_event (MetaDisplay *display,
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
extra = g_strdup_printf ("win: 0x%lx x: %g y: %g",
|
||||
device_event->event,
|
||||
device_event->root_x,
|
||||
device_event->root_y);
|
||||
break;
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
extra = g_strdup_printf ("button %u x %g y %g root 0x%lx",
|
||||
device_event->detail,
|
||||
device_event->root_x,
|
||||
device_event->root_y,
|
||||
device_event->root);
|
||||
break;
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
KeySym keysym;
|
||||
const char *str;
|
||||
|
||||
keysym = XKeycodeToKeysym (display->xdisplay, device_event->detail, 0);
|
||||
|
||||
str = XKeysymToString (keysym);
|
||||
|
||||
extra = g_strdup_printf ("Key '%s' state 0x%x",
|
||||
str ? str : "none", device_event->mods.effective);
|
||||
}
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
extra = g_strdup_printf ("detail: %s mode: %s\n",
|
||||
@@ -3732,7 +3434,7 @@ meta_spew_xi2_event (MetaDisplay *display,
|
||||
*extra_p = extra;
|
||||
}
|
||||
|
||||
static void
|
||||
G_GNUC_UNUSED static void
|
||||
meta_spew_core_event (MetaDisplay *display,
|
||||
XEvent *event,
|
||||
const char **name_p,
|
||||
@@ -3956,7 +3658,7 @@ meta_spew_core_event (MetaDisplay *display,
|
||||
*extra_p = extra;
|
||||
}
|
||||
|
||||
static void
|
||||
G_GNUC_UNUSED static void
|
||||
meta_spew_event (MetaDisplay *display,
|
||||
XEvent *event)
|
||||
{
|
||||
@@ -3965,9 +3667,6 @@ meta_spew_event (MetaDisplay *display,
|
||||
char *winname;
|
||||
MetaScreen *screen;
|
||||
XIEvent *input_event;
|
||||
|
||||
if (!meta_is_verbose())
|
||||
return;
|
||||
|
||||
/* filter overnumerous events */
|
||||
if (event->type == Expose || event->type == MotionNotify ||
|
||||
@@ -3997,18 +3696,16 @@ meta_spew_event (MetaDisplay *display,
|
||||
else
|
||||
winname = g_strdup_printf ("0x%lx", event->xany.window);
|
||||
|
||||
meta_topic (META_DEBUG_EVENTS,
|
||||
"%s on %s%s %s %sserial %lu\n", name, winname,
|
||||
extra ? ":" : "", extra ? extra : "",
|
||||
event->xany.send_event ? "SEND " : "",
|
||||
event->xany.serial);
|
||||
g_print ("%s on %s%s %s %sserial %lu\n", name, winname,
|
||||
extra ? ":" : "", extra ? extra : "",
|
||||
event->xany.send_event ? "SEND " : "",
|
||||
event->xany.serial);
|
||||
|
||||
g_free (winname);
|
||||
|
||||
if (extra)
|
||||
g_free (extra);
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
MetaWindow*
|
||||
meta_display_lookup_x_window (MetaDisplay *display,
|
||||
@@ -4336,7 +4033,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
display->grab_latest_motion_y = root_y;
|
||||
display->grab_last_moveresize_time.tv_sec = 0;
|
||||
display->grab_last_moveresize_time.tv_usec = 0;
|
||||
display->grab_motion_notify_time = 0;
|
||||
display->grab_old_window_stacking = NULL;
|
||||
#ifdef HAVE_XSYNC
|
||||
display->grab_last_user_action_was_snap = FALSE;
|
||||
@@ -4373,16 +4069,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
|
||||
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
||||
|
||||
/* Save the old stacking */
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Saving old stack positions; old pointer was %p.\n",
|
||||
display->grab_old_window_stacking);
|
||||
display->grab_old_window_stacking =
|
||||
meta_stack_get_positions (screen->stack);
|
||||
}
|
||||
|
||||
if (display->grab_window)
|
||||
{
|
||||
meta_window_refresh_resize_popup (display->grab_window);
|
||||
@@ -4424,20 +4110,6 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
if (!display->grab_threshold_movement_reached)
|
||||
meta_window_raise (display->grab_window);
|
||||
}
|
||||
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) ||
|
||||
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING)
|
||||
{
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
meta_screen_tab_popup_destroy (display->grab_screen);
|
||||
else
|
||||
meta_screen_workspace_popup_destroy (display->grab_screen);
|
||||
|
||||
/* If the ungrab here causes an EnterNotify, ignore it for
|
||||
* sloppy focus
|
||||
*/
|
||||
display->ungrab_should_not_cause_focus_window = display->grab_xwindow;
|
||||
}
|
||||
|
||||
/* If this was a move or resize clear out the edge cache */
|
||||
if (meta_grab_op_is_resizing (display->grab_op) ||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <gio/gio.h>
|
||||
#include <meta/keybindings.h>
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
struct _MetaKeyHandler
|
||||
{
|
||||
char *name;
|
||||
@@ -47,9 +48,48 @@ struct _MetaKeyBinding
|
||||
KeyCode keycode;
|
||||
unsigned int mask;
|
||||
MetaVirtualModifier modifiers;
|
||||
gint flags;
|
||||
MetaKeyHandler *handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *combos;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
void meta_display_init_keys (MetaDisplay *display);
|
||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
@@ -77,5 +117,8 @@ gboolean meta_prefs_add_keybinding (const char *name,
|
||||
|
||||
gboolean meta_prefs_remove_keybinding (const char *name);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
|
||||
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
|
||||
|
||||
#include <config.h>
|
||||
#include <meta/main.h>
|
||||
@@ -53,7 +53,7 @@
|
||||
#include "session.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib-unix.h>
|
||||
@@ -190,6 +190,7 @@ static gboolean opt_replace_wm;
|
||||
static gboolean opt_disable_sm;
|
||||
static gboolean opt_sync;
|
||||
static gboolean opt_wayland;
|
||||
static gboolean opt_display_server;
|
||||
|
||||
static GOptionEntry meta_options[] = {
|
||||
{
|
||||
@@ -233,6 +234,11 @@ static GOptionEntry meta_options[] = {
|
||||
N_("Run as a wayland compositor"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_display_server,
|
||||
N_("Run as a full display server, rather than nested")
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -401,8 +407,7 @@ meta_init (void)
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
meta_set_debugging (TRUE);
|
||||
|
||||
/* We consider running from mutter-launch equivalent to running from bare metal. */
|
||||
if (getenv ("WESTON_LAUNCHER_SOCK"))
|
||||
if (opt_display_server)
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
|
||||
meta_set_is_wayland_compositor (opt_wayland);
|
||||
@@ -497,6 +502,32 @@ meta_register_with_session (void)
|
||||
g_free (opt_client_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
meta_activate_session (void)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_wayland_compositor_activate_session (compositor, &error))
|
||||
{
|
||||
g_warning ("Could not activate session: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_run: (skip)
|
||||
*
|
||||
|
||||
@@ -43,4 +43,7 @@ void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <gbm.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
@@ -569,6 +570,9 @@ make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self,
|
||||
wl_fixed_to_int (compositor->seat->pointer.x),
|
||||
wl_fixed_to_int (compositor->seat->pointer.y));
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
@@ -1074,12 +1078,13 @@ get_pointer_position_gdk (int *x,
|
||||
GdkScreen *gscreen;
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
gdevice = gdk_device_manager_get_client_pointer (gmanager);
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1095,9 +1100,12 @@ get_pointer_position_clutter (int *x,
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
*x = point.x;
|
||||
*y = point.y;
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1139,3 +1147,12 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
update_hw_cursor (tracker);
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
@@ -650,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
break;
|
||||
case META_POWER_SAVE_OFF:
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
state = DRM_MODE_DPMS_OFF;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "util-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "monitor-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
|
||||
#define KEY_OVERLAY_KEY "overlay-key"
|
||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
||||
#define KEY_NO_TAB_POPUP "no-tab-popup"
|
||||
|
||||
/* These are the different schemas we are keeping
|
||||
* a GSettings instance for */
|
||||
@@ -112,8 +111,6 @@ static char **workspace_names = NULL;
|
||||
|
||||
static gboolean workspaces_only_on_primary = FALSE;
|
||||
|
||||
static gboolean no_tab_popup = FALSE;
|
||||
|
||||
static char *iso_next_group_option = NULL;
|
||||
|
||||
static void handle_preference_update_enum (GSettings *settings,
|
||||
@@ -365,13 +362,6 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&workspaces_only_on_primary,
|
||||
},
|
||||
{
|
||||
{ KEY_NO_TAB_POPUP,
|
||||
SCHEMA_MUTTER,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
},
|
||||
&no_tab_popup,
|
||||
},
|
||||
{
|
||||
{ "auto-maximize",
|
||||
SCHEMA_MUTTER,
|
||||
@@ -1813,9 +1803,6 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
|
||||
return "WORKSPACES_ONLY_ON_PRIMARY";
|
||||
|
||||
case META_PREF_NO_TAB_POPUP:
|
||||
return "NO_TAB_POPUP";
|
||||
|
||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||
return "DRAGGABLE_BORDER_WIDTH";
|
||||
|
||||
@@ -1869,7 +1856,7 @@ init_bindings (void)
|
||||
pref = g_new0 (MetaKeyPref, 1);
|
||||
pref->name = g_strdup ("overlay-key");
|
||||
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
|
||||
pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
|
||||
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
|
||||
pref->builtin = 1;
|
||||
|
||||
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
|
||||
@@ -1879,7 +1866,7 @@ static gboolean
|
||||
update_binding (MetaKeyPref *binding,
|
||||
gchar **strokes)
|
||||
{
|
||||
GSList *old_bindings, *a, *b;
|
||||
GSList *old_combos, *a, *b;
|
||||
gboolean changed;
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
@@ -1891,8 +1878,8 @@ update_binding (MetaKeyPref *binding,
|
||||
"Binding \"%s\" has new GSettings value\n",
|
||||
binding->name);
|
||||
|
||||
old_bindings = binding->bindings;
|
||||
binding->bindings = NULL;
|
||||
old_combos = binding->combos;
|
||||
binding->combos = NULL;
|
||||
|
||||
for (i = 0; strokes && strokes[i]; i++)
|
||||
{
|
||||
@@ -1933,17 +1920,17 @@ update_binding (MetaKeyPref *binding,
|
||||
combo->keysym = keysym;
|
||||
combo->keycode = keycode;
|
||||
combo->modifiers = mods;
|
||||
binding->bindings = g_slist_prepend (binding->bindings, combo);
|
||||
binding->combos = g_slist_prepend (binding->combos, combo);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
||||
binding->name, keysym, keycode, mods);
|
||||
}
|
||||
|
||||
binding->bindings = g_slist_reverse (binding->bindings);
|
||||
binding->combos = g_slist_reverse (binding->combos);
|
||||
|
||||
a = old_bindings;
|
||||
b = binding->bindings;
|
||||
a = old_combos;
|
||||
b = binding->combos;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((!a && b) || (a && !b))
|
||||
@@ -1968,7 +1955,7 @@ update_binding (MetaKeyPref *binding,
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free_full (old_bindings, g_free);
|
||||
g_slist_free_full (old_combos, g_free);
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -2103,7 +2090,7 @@ meta_prefs_add_keybinding (const char *name,
|
||||
pref->name = g_strdup (name);
|
||||
pref->settings = g_object_ref (settings);
|
||||
pref->action = action;
|
||||
pref->bindings = NULL;
|
||||
pref->combos = NULL;
|
||||
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
||||
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
||||
@@ -2167,11 +2154,6 @@ meta_prefs_remove_keybinding (const char *name)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_get_keybindings:
|
||||
*
|
||||
* Returns: (element-type MetaKeyPref) (transfer container):
|
||||
*/
|
||||
GList *
|
||||
meta_prefs_get_keybindings ()
|
||||
{
|
||||
@@ -2272,7 +2254,7 @@ meta_prefs_get_window_binding (const char *name,
|
||||
|
||||
if (pref->per_window)
|
||||
{
|
||||
GSList *s = pref->bindings;
|
||||
GSList *s = pref->combos;
|
||||
|
||||
while (s)
|
||||
{
|
||||
@@ -2320,25 +2302,6 @@ meta_prefs_get_workspaces_only_on_primary (void)
|
||||
return workspaces_only_on_primary;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_no_tab_popup (void)
|
||||
{
|
||||
return no_tab_popup;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_no_tab_popup (gboolean whether)
|
||||
{
|
||||
MetaBasePreference *pref;
|
||||
|
||||
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
|
||||
KEY_NO_TAB_POPUP, &pref))
|
||||
{
|
||||
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
meta_prefs_get_draggable_border_width (void)
|
||||
{
|
||||
|
||||
@@ -64,7 +64,6 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
|
||||
guint tile_preview_timeout_id;
|
||||
|
||||
@@ -150,22 +149,6 @@ void meta_screen_foreach_window (MetaScreen *scree
|
||||
|
||||
void meta_screen_update_cursor (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_window);
|
||||
void meta_screen_tab_popup_forward (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_backward (MetaScreen *screen);
|
||||
MetaWindow* meta_screen_tab_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection);
|
||||
void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace);
|
||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
gboolean delay);
|
||||
void meta_screen_hide_tile_preview (MetaScreen *screen);
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "core.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
@@ -308,6 +308,8 @@ set_supported_hint (MetaScreen *screen)
|
||||
#include <meta/atomnames.h>
|
||||
#undef item
|
||||
#undef EWMH_ATOMS_ONLY
|
||||
|
||||
screen->display->atom__GTK_FRAME_EXTENTS,
|
||||
};
|
||||
|
||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||
@@ -760,9 +762,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
|
||||
screen->tab_popup = NULL;
|
||||
screen->ws_popup = NULL;
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
screen->stack = meta_stack_new (screen);
|
||||
@@ -1428,253 +1427,6 @@ meta_screen_update_cursor (MetaScreen *screen)
|
||||
screen->current_cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
GList *tab_list;
|
||||
GList *tmp;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (screen->tab_popup)
|
||||
return;
|
||||
|
||||
tab_list = meta_display_get_tab_list (screen->display,
|
||||
list_type,
|
||||
screen,
|
||||
screen->active_workspace);
|
||||
|
||||
len = g_list_length (tab_list);
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
tmp = tab_list;
|
||||
while (i < len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaRectangle r;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) window;
|
||||
entries[i].title = window->title;
|
||||
entries[i].icon = g_object_ref (window->icon);
|
||||
entries[i].blank = FALSE;
|
||||
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entries[i].demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||
!entries[i].hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_frame_rect (window, &r);
|
||||
|
||||
entries[i].rect = r;
|
||||
|
||||
/* Find inside of highlight rectangle to be used when window is
|
||||
* outlined for tabbing. This should be the size of the
|
||||
* east/west frame, and the size of the south frame, on those
|
||||
* sides. On the top it should be the size of the south frame
|
||||
* edge.
|
||||
*/
|
||||
#define OUTLINE_WIDTH 5
|
||||
/* Top side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height > 0 &&
|
||||
window->frame->child_y >= window->frame->bottom_height)
|
||||
entries[i].inner_rect.y = window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.y = OUTLINE_WIDTH;
|
||||
|
||||
/* Bottom side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height != 0)
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - OUTLINE_WIDTH;
|
||||
|
||||
/* Left side */
|
||||
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
|
||||
entries[i].inner_rect.x = window->frame->child_x;
|
||||
else
|
||||
entries[i].inner_rect.x = OUTLINE_WIDTH;
|
||||
|
||||
/* Right side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->right_width != 0)
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - window->frame->right_width;
|
||||
else
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - OUTLINE_WIDTH;
|
||||
|
||||
++i;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (!meta_prefs_get_no_tab_popup ())
|
||||
screen->tab_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
5, /* FIXME */
|
||||
TRUE);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
g_object_unref (entries[i].icon);
|
||||
|
||||
g_free (entries);
|
||||
|
||||
g_list_free (tab_list);
|
||||
|
||||
meta_ui_tab_popup_select (screen->tab_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
|
||||
if (show_type != META_TAB_SHOW_INSTANTLY)
|
||||
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_forward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_forward (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_backward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_backward (screen->tab_popup);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_screen_tab_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
|
||||
|
||||
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (screen->tab_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->tab_popup);
|
||||
screen->tab_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
int len;
|
||||
int i;
|
||||
MetaWorkspaceLayout layout;
|
||||
int n_workspaces;
|
||||
int current_workspace;
|
||||
|
||||
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
|
||||
return;
|
||||
|
||||
current_workspace = meta_workspace_index (screen->active_workspace);
|
||||
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||
|
||||
meta_screen_calc_workspace_layout (screen, n_workspaces,
|
||||
current_workspace, &layout);
|
||||
|
||||
len = layout.grid_area;
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
if (layout.grid[i] >= 0)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
workspace = meta_screen_get_workspace_by_index (screen,
|
||||
layout.grid[i]);
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) workspace;
|
||||
entries[i].title = meta_workspace_get_name (workspace);
|
||||
entries[i].icon = NULL;
|
||||
entries[i].blank = FALSE;
|
||||
|
||||
g_assert (entries[i].title != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
entries[i].key = NULL;
|
||||
entries[i].title = NULL;
|
||||
entries[i].icon = NULL;
|
||||
entries[i].blank = TRUE;
|
||||
}
|
||||
entries[i].hidden = FALSE;
|
||||
entries[i].demands_attention = FALSE;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
screen->ws_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
layout.cols,
|
||||
FALSE);
|
||||
|
||||
g_free (entries);
|
||||
meta_screen_free_workspace_layout (&layout);
|
||||
|
||||
meta_ui_tab_popup_select (screen->ws_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
g_return_if_fail (screen->ws_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_select (screen->ws_popup,
|
||||
(MetaTabEntryKey) workspace);
|
||||
}
|
||||
|
||||
MetaWorkspace *
|
||||
meta_screen_workspace_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->ws_popup != NULL, NULL);
|
||||
|
||||
return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (screen->ws_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->ws_popup);
|
||||
screen->ws_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_update_tile_preview_timeout (gpointer data)
|
||||
{
|
||||
@@ -1762,38 +1514,19 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one)
|
||||
{
|
||||
MetaWindow *window;
|
||||
Window root_return, child_return;
|
||||
double root_x_return, root_y_return;
|
||||
double win_x_return, win_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int x, y;
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_error_trap_push (screen->display);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
meta_error_trap_pop (screen->display);
|
||||
free (buttons.mask);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
not_this_one,
|
||||
root_x_return,
|
||||
root_y_return);
|
||||
x, y);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -2075,28 +1808,11 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
Window root_return, child_return;
|
||||
double win_x_return, win_y_return;
|
||||
double root_x_return, root_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int x, y;
|
||||
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
free (buttons.mask);
|
||||
|
||||
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_screen_get_current_monitor_for_pos (screen, x, y);
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
|
||||
@@ -92,7 +92,6 @@ struct _MetaWindow
|
||||
char *icon_name;
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
MetaIconCache icon_cache;
|
||||
Pixmap wm_hints_pixmap;
|
||||
Pixmap wm_hints_mask;
|
||||
|
||||
@@ -684,9 +683,8 @@ void meta_window_update_layer (MetaWindow *window);
|
||||
|
||||
void meta_window_recalc_features (MetaWindow *window);
|
||||
|
||||
/* recalc_window_type is x11 only, wayland does its thing and then calls type_changed */
|
||||
void meta_window_recalc_window_type (MetaWindow *window);
|
||||
void meta_window_type_changed (MetaWindow *window);
|
||||
void meta_window_set_type (MetaWindow *window,
|
||||
MetaWindowType type);
|
||||
|
||||
void meta_window_frame_size_changed (MetaWindow *window);
|
||||
|
||||
@@ -743,9 +741,14 @@ void meta_window_set_surface_mapped (MetaWindow *window,
|
||||
|
||||
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
|
||||
|
||||
void meta_window_get_client_area_rect (const MetaWindow *window,
|
||||
cairo_rectangle_int_t *rect);
|
||||
|
||||
void meta_window_activate_full (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaClientType source_indication,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
gboolean meta_window_is_client_decorated (MetaWindow *window);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _SVID_SOURCE /* for gethostname() */
|
||||
#define _XOPEN_SOURCE 500 /* for gethostname() */
|
||||
|
||||
#include <config.h>
|
||||
#include "window-props.h"
|
||||
@@ -237,9 +237,6 @@ static void
|
||||
reload_icon (MetaWindow *window,
|
||||
Atom atom)
|
||||
{
|
||||
meta_icon_cache_property_changed (&window->icon_cache,
|
||||
window->display,
|
||||
atom);
|
||||
meta_window_queue(window, META_QUEUE_UPDATE_ICON);
|
||||
}
|
||||
|
||||
@@ -727,7 +724,7 @@ reload_net_wm_state (MetaWindow *window,
|
||||
meta_verbose ("Reloaded _NET_WM_STATE for %s\n",
|
||||
window->desc);
|
||||
|
||||
meta_window_recalc_window_type (window);
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
meta_window_recalc_features (window);
|
||||
}
|
||||
|
||||
@@ -1503,10 +1500,6 @@ reload_wm_hints (MetaWindow *window,
|
||||
if (!initial && window->wm_hints_urgent && !old_urgent)
|
||||
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
|
||||
|
||||
meta_icon_cache_property_changed (&window->icon_cache,
|
||||
window->display,
|
||||
XA_WM_HINTS);
|
||||
|
||||
meta_window_queue (window, META_QUEUE_UPDATE_ICON | META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <meta/common.h>
|
||||
#include <meta/errors.h>
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "window-private.h"
|
||||
#include "window-props.h"
|
||||
@@ -225,7 +226,7 @@ meta_window_x11_update_net_wm_type (MetaWindow *window)
|
||||
meta_XFree (str);
|
||||
}
|
||||
|
||||
meta_window_recalc_window_type (window);
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -350,11 +351,43 @@ meta_window_set_input_region (MetaWindow *window,
|
||||
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Print out a region; useful for debugging */
|
||||
static void
|
||||
print_region (cairo_region_t *region)
|
||||
{
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
g_print ("[");
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
g_print ("+%d+%dx%dx%d ",
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
g_print ("]\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_window_x11_update_input_region (MetaWindow *window)
|
||||
{
|
||||
cairo_region_t *region = NULL;
|
||||
|
||||
/* Decorated windows don't have an input region, because
|
||||
we don't shape the frame to match the client windows
|
||||
(so the events are blocked by the frame anyway)
|
||||
*/
|
||||
if (window->decorated)
|
||||
{
|
||||
if (window->input_region)
|
||||
meta_window_set_input_region (window, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (window->display))
|
||||
{
|
||||
@@ -363,17 +396,7 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
XRectangle *rects = NULL;
|
||||
int n_rects, ordering;
|
||||
|
||||
int x_bounding, y_bounding, x_clip, y_clip;
|
||||
unsigned w_bounding, h_bounding, w_clip, h_clip;
|
||||
int bounding_shaped, clip_shaped;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
|
||||
&bounding_shaped, &x_bounding, &y_bounding,
|
||||
&w_bounding, &h_bounding,
|
||||
&clip_shaped, &x_clip, &y_clip,
|
||||
&w_clip, &h_clip);
|
||||
|
||||
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
ShapeInput,
|
||||
@@ -388,10 +411,10 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
{
|
||||
if (n_rects > 1 ||
|
||||
(n_rects == 1 &&
|
||||
(rects[0].x != x_bounding ||
|
||||
rects[0].y != y_bounding ||
|
||||
rects[0].width != w_bounding ||
|
||||
rects[0].height != h_bounding)))
|
||||
(rects[0].x != 0 ||
|
||||
rects[0].y != 0 ||
|
||||
rects[0].width != window->rect.width ||
|
||||
rects[0].height != window->rect.height)))
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
|
||||
XFree (rects);
|
||||
@@ -651,35 +674,19 @@ meta_window_x11_property_notify (MetaWindow *window,
|
||||
static int
|
||||
query_pressed_buttons (MetaWindow *window)
|
||||
{
|
||||
double x, y, query_root_x, query_root_y;
|
||||
Window root, child;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
ClutterModifierType mods;
|
||||
int button = 0;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XIQueryPointer (window->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
window->xwindow,
|
||||
&root, &child,
|
||||
&query_root_x, &query_root_y,
|
||||
&x, &y,
|
||||
&buttons, &mods, &group);
|
||||
meta_cursor_tracker_get_pointer (window->screen->cursor_tracker,
|
||||
NULL, NULL, &mods);
|
||||
|
||||
if (meta_error_trap_pop_with_return (window->display) != Success)
|
||||
goto out;
|
||||
|
||||
if (XIMaskIsSet (buttons.mask, Button1))
|
||||
if (mods & CLUTTER_BUTTON1_MASK)
|
||||
button |= 1 << 1;
|
||||
if (XIMaskIsSet (buttons.mask, Button2))
|
||||
if (mods & CLUTTER_BUTTON2_MASK)
|
||||
button |= 1 << 2;
|
||||
if (XIMaskIsSet (buttons.mask, Button3))
|
||||
if (mods & CLUTTER_BUTTON3_MASK)
|
||||
button |= 1 << 3;
|
||||
|
||||
free (buttons.mask);
|
||||
|
||||
out:
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -865,7 +872,7 @@ meta_window_x11_client_message (MetaWindow *window,
|
||||
(action == _NET_WM_STATE_ADD) ||
|
||||
(action == _NET_WM_STATE_TOGGLE && !window->wm_state_modal);
|
||||
|
||||
meta_window_recalc_window_type (window);
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
@@ -1453,6 +1460,11 @@ meta_window_x11_new (MetaDisplay *display,
|
||||
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (display))
|
||||
XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask);
|
||||
#endif
|
||||
|
||||
/* Get rid of any borders */
|
||||
if (attrs.border_width != 0)
|
||||
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
|
||||
@@ -1494,3 +1506,114 @@ error:
|
||||
meta_error_trap_pop (display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_x11_recalc_window_type (MetaWindow *window)
|
||||
{
|
||||
MetaWindowType type;
|
||||
|
||||
if (window->type_atom != None)
|
||||
{
|
||||
if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP)
|
||||
type = META_WINDOW_DESKTOP;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DOCK)
|
||||
type = META_WINDOW_DOCK;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR)
|
||||
type = META_WINDOW_TOOLBAR;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_MENU)
|
||||
type = META_WINDOW_MENU;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY)
|
||||
type = META_WINDOW_UTILITY;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH)
|
||||
type = META_WINDOW_SPLASHSCREEN;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG)
|
||||
type = META_WINDOW_DIALOG;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL)
|
||||
type = META_WINDOW_NORMAL;
|
||||
/* The below are *typically* override-redirect windows, but the spec does
|
||||
* not disallow using them for managed windows.
|
||||
*/
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
|
||||
type = META_WINDOW_DROPDOWN_MENU;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU)
|
||||
type = META_WINDOW_POPUP_MENU;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLTIP)
|
||||
type = META_WINDOW_TOOLTIP;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION)
|
||||
type = META_WINDOW_NOTIFICATION;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_COMBO)
|
||||
type = META_WINDOW_COMBO;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DND)
|
||||
type = META_WINDOW_DND;
|
||||
else
|
||||
{
|
||||
char *atom_name;
|
||||
|
||||
/*
|
||||
* Fallback on a normal type, and print warning. Don't abort.
|
||||
*/
|
||||
type = META_WINDOW_NORMAL;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
atom_name = XGetAtomName (window->display->xdisplay,
|
||||
window->type_atom);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
meta_warning ("Unrecognized type atom [%s] set for %s \n",
|
||||
atom_name ? atom_name : "unknown",
|
||||
window->desc);
|
||||
|
||||
if (atom_name)
|
||||
XFree (atom_name);
|
||||
}
|
||||
}
|
||||
else if (window->transient_for != NULL)
|
||||
{
|
||||
type = META_WINDOW_DIALOG;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = META_WINDOW_NORMAL;
|
||||
}
|
||||
|
||||
if (type == META_WINDOW_DIALOG &&
|
||||
window->wm_state_modal)
|
||||
type = META_WINDOW_MODAL_DIALOG;
|
||||
|
||||
/* We don't want to allow override-redirect windows to have decorated-window
|
||||
* types since that's just confusing.
|
||||
*/
|
||||
if (window->override_redirect)
|
||||
{
|
||||
switch (window->type)
|
||||
{
|
||||
/* Decorated types */
|
||||
case META_WINDOW_NORMAL:
|
||||
case META_WINDOW_DIALOG:
|
||||
case META_WINDOW_MODAL_DIALOG:
|
||||
case META_WINDOW_MENU:
|
||||
case META_WINDOW_UTILITY:
|
||||
type = META_WINDOW_OVERRIDE_OTHER;
|
||||
break;
|
||||
/* Undecorated types, normally not override-redirect */
|
||||
case META_WINDOW_DESKTOP:
|
||||
case META_WINDOW_DOCK:
|
||||
case META_WINDOW_TOOLBAR:
|
||||
case META_WINDOW_SPLASHSCREEN:
|
||||
/* Undecorated types, normally override-redirect types */
|
||||
case META_WINDOW_DROPDOWN_MENU:
|
||||
case META_WINDOW_POPUP_MENU:
|
||||
case META_WINDOW_TOOLTIP:
|
||||
case META_WINDOW_NOTIFICATION:
|
||||
case META_WINDOW_COMBO:
|
||||
case META_WINDOW_DND:
|
||||
/* To complete enum */
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Calculated type %u for %s, old type %u\n",
|
||||
type, window->desc, type);
|
||||
meta_window_set_type (window, type);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ void meta_window_x11_update_opaque_region (MetaWindow *window);
|
||||
void meta_window_x11_update_input_region (MetaWindow *window);
|
||||
void meta_window_x11_update_shape_region (MetaWindow *window);
|
||||
|
||||
void meta_window_x11_recalc_window_type (MetaWindow *window);
|
||||
|
||||
gboolean meta_window_x11_configure_request (MetaWindow *window,
|
||||
XEvent *event);
|
||||
gboolean meta_window_x11_property_notify (MetaWindow *window,
|
||||
|
||||
@@ -233,8 +233,6 @@ meta_window_finalize (GObject *object)
|
||||
if (window->transient_for)
|
||||
g_object_unref (window->transient_for);
|
||||
|
||||
meta_icon_cache_free (&window->icon_cache);
|
||||
|
||||
g_free (window->sm_client_id);
|
||||
g_free (window->wm_client_machine);
|
||||
g_free (window->startup_id);
|
||||
@@ -818,7 +816,6 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->icon_name = NULL;
|
||||
window->icon = NULL;
|
||||
window->mini_icon = NULL;
|
||||
meta_icon_cache_init (&window->icon_cache);
|
||||
window->wm_hints_pixmap = None;
|
||||
window->wm_hints_mask = None;
|
||||
window->wm_hints_urgent = FALSE;
|
||||
@@ -993,6 +990,9 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
update_sm_hints (window); /* must come after transient_for */
|
||||
|
||||
if (client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
meta_window_x11_update_net_wm_type (window);
|
||||
|
||||
if (!window->override_redirect)
|
||||
meta_window_update_icon_now (window);
|
||||
|
||||
@@ -3117,6 +3117,9 @@ meta_window_maximize_internal (MetaWindow *window,
|
||||
meta_window_recalc_features (window);
|
||||
set_net_wm_state (window);
|
||||
|
||||
if (window->surface && window->maximized_horizontally && window->maximized_vertically)
|
||||
meta_wayland_surface_send_maximized (window->surface);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
@@ -3602,10 +3605,13 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
set_net_wm_state (window);
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
if (window->surface && !window->maximized_horizontally && !window->maximized_vertically)
|
||||
meta_wayland_surface_send_unmaximized (window->surface);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3708,6 +3714,9 @@ meta_window_make_fullscreen_internal (MetaWindow *window)
|
||||
/* For the auto-minimize feature, if we fail to get focus */
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
|
||||
if (window->surface)
|
||||
meta_wayland_surface_send_fullscreened (window->surface);
|
||||
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
}
|
||||
@@ -3764,6 +3773,9 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
|
||||
meta_window_update_layer (window);
|
||||
|
||||
if (window->surface)
|
||||
meta_wayland_surface_send_unfullscreened (window->surface);
|
||||
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
}
|
||||
@@ -5079,6 +5091,7 @@ meta_window_move_resize_wayland (MetaWindow *window,
|
||||
|
||||
meta_window_move_resize_internal (window, flags, NorthWestGravity,
|
||||
x, y, width, height);
|
||||
save_user_window_placement (window);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5648,6 +5661,37 @@ meta_window_get_outer_rect (const MetaWindow *window,
|
||||
meta_window_get_frame_rect (window, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_client_area_rect:
|
||||
* @window: a #MetaWindow
|
||||
* @rect: (out): pointer to a cairo rectangle
|
||||
*
|
||||
* Gets the rectangle for the boundaries of the client area, relative
|
||||
* to the frame. If the window is shaded, the height of the rectangle
|
||||
* is 0.
|
||||
*/
|
||||
void
|
||||
meta_window_get_client_area_rect (const MetaWindow *window,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
if (window->frame)
|
||||
{
|
||||
rect->x = window->frame->child_x;
|
||||
rect->y = window->frame->child_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->x = 0;
|
||||
rect->y = 0;
|
||||
}
|
||||
|
||||
rect->width = window->rect.width;
|
||||
if (window->shaded)
|
||||
rect->height = 0;
|
||||
else
|
||||
rect->height = window->rect.height;
|
||||
}
|
||||
|
||||
const char*
|
||||
meta_window_get_startup_id (MetaWindow *window)
|
||||
{
|
||||
@@ -6746,25 +6790,13 @@ meta_window_update_icon_now (MetaWindow *window)
|
||||
icon = NULL;
|
||||
mini_icon = NULL;
|
||||
|
||||
if (meta_read_icons (window->screen,
|
||||
window->xwindow,
|
||||
&window->icon_cache,
|
||||
window->wm_hints_pixmap,
|
||||
window->wm_hints_mask,
|
||||
&icon,
|
||||
META_ICON_WIDTH, META_ICON_HEIGHT,
|
||||
&mini_icon,
|
||||
META_MINI_ICON_WIDTH,
|
||||
META_MINI_ICON_HEIGHT))
|
||||
if (read_icons (window->screen,
|
||||
window->xwindow,
|
||||
window->wm_hints_pixmap,
|
||||
window->wm_hints_mask,
|
||||
&window->icon))
|
||||
{
|
||||
if (window->icon)
|
||||
g_object_unref (G_OBJECT (window->icon));
|
||||
|
||||
if (window->mini_icon)
|
||||
g_object_unref (G_OBJECT (window->mini_icon));
|
||||
|
||||
window->icon = icon;
|
||||
window->mini_icon = mini_icon;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "icon");
|
||||
@@ -7017,122 +7049,7 @@ meta_window_update_struts (MetaWindow *window)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_recalc_window_type (MetaWindow *window)
|
||||
{
|
||||
MetaWindowType old_type;
|
||||
|
||||
old_type = window->type;
|
||||
|
||||
if (window->type_atom != None)
|
||||
{
|
||||
if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP)
|
||||
window->type = META_WINDOW_DESKTOP;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DOCK)
|
||||
window->type = META_WINDOW_DOCK;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR)
|
||||
window->type = META_WINDOW_TOOLBAR;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_MENU)
|
||||
window->type = META_WINDOW_MENU;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY)
|
||||
window->type = META_WINDOW_UTILITY;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH)
|
||||
window->type = META_WINDOW_SPLASHSCREEN;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG)
|
||||
window->type = META_WINDOW_DIALOG;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL)
|
||||
window->type = META_WINDOW_NORMAL;
|
||||
/* The below are *typically* override-redirect windows, but the spec does
|
||||
* not disallow using them for managed windows.
|
||||
*/
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
|
||||
window->type = META_WINDOW_DROPDOWN_MENU;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU)
|
||||
window->type = META_WINDOW_POPUP_MENU;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLTIP)
|
||||
window->type = META_WINDOW_TOOLTIP;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION)
|
||||
window->type = META_WINDOW_NOTIFICATION;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_COMBO)
|
||||
window->type = META_WINDOW_COMBO;
|
||||
else if (window->type_atom == window->display->atom__NET_WM_WINDOW_TYPE_DND)
|
||||
window->type = META_WINDOW_DND;
|
||||
else
|
||||
{
|
||||
char *atom_name;
|
||||
|
||||
/*
|
||||
* Fallback on a normal type, and print warning. Don't abort.
|
||||
*/
|
||||
window->type = META_WINDOW_NORMAL;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
atom_name = XGetAtomName (window->display->xdisplay,
|
||||
window->type_atom);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
meta_warning ("Unrecognized type atom [%s] set for %s \n",
|
||||
atom_name ? atom_name : "unknown",
|
||||
window->desc);
|
||||
|
||||
if (atom_name)
|
||||
XFree (atom_name);
|
||||
}
|
||||
}
|
||||
else if (window->transient_for != NULL)
|
||||
{
|
||||
window->type = META_WINDOW_DIALOG;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->type = META_WINDOW_NORMAL;
|
||||
}
|
||||
|
||||
if (window->type == META_WINDOW_DIALOG &&
|
||||
window->wm_state_modal)
|
||||
window->type = META_WINDOW_MODAL_DIALOG;
|
||||
|
||||
/* We don't want to allow override-redirect windows to have decorated-window
|
||||
* types since that's just confusing.
|
||||
*/
|
||||
if (window->override_redirect)
|
||||
{
|
||||
switch (window->type)
|
||||
{
|
||||
/* Decorated types */
|
||||
case META_WINDOW_NORMAL:
|
||||
case META_WINDOW_DIALOG:
|
||||
case META_WINDOW_MODAL_DIALOG:
|
||||
case META_WINDOW_MENU:
|
||||
case META_WINDOW_UTILITY:
|
||||
window->type = META_WINDOW_OVERRIDE_OTHER;
|
||||
break;
|
||||
/* Undecorated types, normally not override-redirect */
|
||||
case META_WINDOW_DESKTOP:
|
||||
case META_WINDOW_DOCK:
|
||||
case META_WINDOW_TOOLBAR:
|
||||
case META_WINDOW_SPLASHSCREEN:
|
||||
/* Undecorated types, normally override-redirect types */
|
||||
case META_WINDOW_DROPDOWN_MENU:
|
||||
case META_WINDOW_POPUP_MENU:
|
||||
case META_WINDOW_TOOLTIP:
|
||||
case META_WINDOW_NOTIFICATION:
|
||||
case META_WINDOW_COMBO:
|
||||
case META_WINDOW_DND:
|
||||
/* To complete enum */
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Calculated type %u for %s, old type %u\n",
|
||||
window->type, window->desc, old_type);
|
||||
|
||||
if (old_type != window->type)
|
||||
meta_window_type_changed (window);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_window_type_changed (MetaWindow *window)
|
||||
{
|
||||
gboolean old_decorated = window->decorated;
|
||||
@@ -7165,6 +7082,17 @@ meta_window_type_changed (MetaWindow *window)
|
||||
g_object_thaw_notify (object);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_type (MetaWindow *window,
|
||||
MetaWindowType type)
|
||||
{
|
||||
if (window->type == type)
|
||||
return;
|
||||
|
||||
window->type = type;
|
||||
meta_window_type_changed (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_frame_size_changed (MetaWindow *window)
|
||||
{
|
||||
@@ -7806,7 +7734,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
|
||||
/* Titlebar can't be offscreen if there is no titlebar... */
|
||||
if (!window->frame)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
||||
/* Get the rectangle corresponding to the titlebar */
|
||||
meta_window_get_frame_rect (window, &titlebar_rect);
|
||||
@@ -8487,98 +8415,6 @@ update_resize (MetaWindow *window,
|
||||
g_get_current_time (&window->display->grab_last_moveresize_time);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Window window;
|
||||
int count;
|
||||
guint32 last_time;
|
||||
} EventScannerData;
|
||||
|
||||
static Bool
|
||||
find_last_time_predicate (Display *display,
|
||||
XEvent *ev,
|
||||
XPointer arg)
|
||||
{
|
||||
EventScannerData *esd = (void*) arg;
|
||||
XIEvent *xev;
|
||||
|
||||
if (ev->type != GenericEvent)
|
||||
return False;
|
||||
|
||||
/* We are peeking into events not yet handled by GDK,
|
||||
* Allocate cookie events here so we can handle XI2.
|
||||
*
|
||||
* GDK will handle later these events, and eventually
|
||||
* free the cookie data itself.
|
||||
*/
|
||||
XGetEventData (display, &ev->xcookie);
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype != XI_Motion)
|
||||
return False;
|
||||
|
||||
if (esd->window != ((XIDeviceEvent *) xev)->event)
|
||||
return False;
|
||||
|
||||
esd->count += 1;
|
||||
esd->last_time = xev->time;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_use_this_motion_notify (MetaWindow *window,
|
||||
XIDeviceEvent *xev)
|
||||
{
|
||||
EventScannerData esd;
|
||||
XEvent useless;
|
||||
|
||||
/* This code is copied from Owen's GDK code. */
|
||||
|
||||
if (window->display->grab_motion_notify_time != 0)
|
||||
{
|
||||
/* == is really the right test, but I'm all for paranoia */
|
||||
if (window->display->grab_motion_notify_time <=
|
||||
xev->time)
|
||||
{
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Arrived at event with time %u (waiting for %u), using it\n",
|
||||
(unsigned int)xev->time,
|
||||
window->display->grab_motion_notify_time);
|
||||
window->display->grab_motion_notify_time = 0;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; /* haven't reached the saved timestamp yet */
|
||||
}
|
||||
|
||||
esd.window = xev->event;
|
||||
esd.count = 0;
|
||||
esd.last_time = 0;
|
||||
|
||||
/* "useless" isn't filled in because the predicate never returns True */
|
||||
XCheckIfEvent (window->display->xdisplay,
|
||||
&useless,
|
||||
find_last_time_predicate,
|
||||
(XPointer) &esd);
|
||||
|
||||
if (esd.count > 0)
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Will skip %d motion events and use the event with time %u\n",
|
||||
esd.count, (unsigned int) esd.last_time);
|
||||
|
||||
if (esd.last_time == 0)
|
||||
return TRUE;
|
||||
else
|
||||
{
|
||||
/* Save this timestamp, and ignore all motion notify
|
||||
* until we get to the one with this stamp.
|
||||
*/
|
||||
window->display->grab_motion_notify_time = esd.last_time;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_tile_mode (MetaWindow *window)
|
||||
{
|
||||
@@ -8649,96 +8485,6 @@ meta_window_update_sync_request_counter (MetaWindow *window,
|
||||
}
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
void
|
||||
meta_window_handle_mouse_grab_op_xevent (MetaWindow *window,
|
||||
XIDeviceEvent *xevent)
|
||||
{
|
||||
gboolean is_window_root = (xevent->root == window->screen->xroot);
|
||||
|
||||
switch (xevent->evtype)
|
||||
{
|
||||
case XI_ButtonRelease:
|
||||
if (xevent->detail == 1 ||
|
||||
xevent->detail == meta_prefs_get_mouse_button_resize ())
|
||||
{
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
/* If the user was snap moving then ignore the button
|
||||
* release because they may have let go of shift before
|
||||
* releasing the mouse button and they almost certainly do
|
||||
* not want a non-snapped movement to occur from the button
|
||||
* release.
|
||||
*/
|
||||
if (!window->display->grab_last_user_action_was_snap)
|
||||
{
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else if (is_window_root)
|
||||
update_move (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
update_resize (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y,
|
||||
TRUE);
|
||||
|
||||
/* If a tiled window has been dragged free with a
|
||||
* mouse resize without snapping back to the tiled
|
||||
* state, it will end up with an inconsistent tile
|
||||
* mode on mouse release; cleaning the mode earlier
|
||||
* would break the ability to snap back to the tiled
|
||||
* state, so we wait until mouse release.
|
||||
*/
|
||||
update_tile_mode (window);
|
||||
}
|
||||
meta_display_end_grab_op (window->display, xevent->time);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XI_Motion:
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
{
|
||||
if (check_use_this_motion_notify (window, xevent))
|
||||
update_move (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
}
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
{
|
||||
if (check_use_this_motion_notify (window, xevent))
|
||||
update_resize (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
@@ -9003,6 +8749,34 @@ meta_window_same_application (MetaWindow *window,
|
||||
group==other_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_is_client_decorated:
|
||||
*
|
||||
* Check if if the window has decorations drawn by the client.
|
||||
* (window->decorated refers only to whether we should add decorations)
|
||||
*/
|
||||
gboolean
|
||||
meta_window_is_client_decorated (MetaWindow *window)
|
||||
{
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
/* Assume all Wayland clients draw decorations - not strictly
|
||||
* true but good enough for current purposes.
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Currently the implementation here is hackish -
|
||||
* has_custom_frame_extents() is set if _GTK_FRAME_EXTENTS is set
|
||||
* to any value even 0. GTK+ always sets _GTK_FRAME_EXTENTS for
|
||||
* client-side-decorated window, even if the value is 0 because
|
||||
* the window is maxized and has no invisible borders or shadows.
|
||||
*/
|
||||
return window->has_custom_frame_extents;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_refresh_resize_popup (MetaWindow *window)
|
||||
{
|
||||
@@ -10365,7 +10139,8 @@ meta_window_set_transient_for (MetaWindow *window,
|
||||
meta_window_propagate_focus_appearance (window, FALSE);
|
||||
|
||||
/* may now be a dialog */
|
||||
meta_window_recalc_window_type (window);
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
|
||||
if (!window->constructing)
|
||||
{
|
||||
@@ -10491,25 +10266,15 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
MetaWindow *window = focus_data->window;
|
||||
MetaDisplay *display = window->display;
|
||||
MetaScreen *screen = window->screen;
|
||||
Window root, child;
|
||||
double root_x, root_y, x, y;
|
||||
int root_x, root_y;
|
||||
guint32 timestamp;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
ClutterActor *child;
|
||||
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
|
||||
goto out;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XIQueryPointer (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root, &child,
|
||||
&root_x, &root_y, &x, &y,
|
||||
&buttons, &mods, &group);
|
||||
meta_error_trap_pop (display);
|
||||
free (buttons.mask);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&root_x, &root_y, NULL);
|
||||
|
||||
if (root_x != focus_data->pointer_x ||
|
||||
root_y != focus_data->pointer_y)
|
||||
@@ -10519,17 +10284,15 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Explicitly check for the overlay window, as get_focus_window_at_point()
|
||||
* may return windows that extend underneath the chrome (like
|
||||
* override-redirect or DESKTOP windows)
|
||||
*/
|
||||
if (child == meta_get_overlay_window (screen))
|
||||
child = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (clutter_stage_get_default ()),
|
||||
CLUTTER_PICK_REACTIVE, root_x, root_y);
|
||||
if (!META_IS_SURFACE_ACTOR (child))
|
||||
goto out;
|
||||
|
||||
window =
|
||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
None, root_x, root_y);
|
||||
NULL, root_x, root_y);
|
||||
|
||||
if (window == NULL)
|
||||
goto out;
|
||||
|
||||
@@ -214,21 +214,6 @@ typedef enum
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_SW,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_NW,
|
||||
|
||||
/* Alt+Tab */
|
||||
META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
|
||||
META_GRAB_OP_KEYBOARD_TABBING_DOCK,
|
||||
|
||||
/* Alt+Esc */
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL,
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_DOCK,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_GROUP,
|
||||
|
||||
/* Alt+F6 */
|
||||
META_GRAB_OP_KEYBOARD_TABBING_GROUP,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING,
|
||||
|
||||
/* Frame button ops */
|
||||
META_GRAB_OP_CLICKING_MINIMIZE,
|
||||
META_GRAB_OP_CLICKING_MAXIMIZE,
|
||||
@@ -243,7 +228,10 @@ typedef enum
|
||||
META_GRAB_OP_CLICKING_UNSTICK,
|
||||
|
||||
/* Special grab op when the compositor asked for a grab */
|
||||
META_GRAB_OP_COMPOSITOR
|
||||
META_GRAB_OP_COMPOSITOR,
|
||||
|
||||
/* For when a client takes a popup grab */
|
||||
META_GRAB_OP_WAYLAND_CLIENT,
|
||||
} MetaGrabOp;
|
||||
|
||||
/**
|
||||
@@ -504,12 +492,6 @@ struct _MetaFrameBorders
|
||||
/* sets all dimensions to zero */
|
||||
void meta_frame_borders_clear (MetaFrameBorders *self);
|
||||
|
||||
/* should investigate changing these to whatever most apps use */
|
||||
#define META_ICON_WIDTH 96
|
||||
#define META_ICON_HEIGHT 96
|
||||
#define META_MINI_ICON_WIDTH 16
|
||||
#define META_MINI_ICON_HEIGHT 16
|
||||
|
||||
#define META_DEFAULT_ICON_NAME "window"
|
||||
|
||||
/* Main loop priorities determine when activity in the GLib
|
||||
|
||||
@@ -66,6 +66,8 @@ void meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
gboolean meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
|
||||
@@ -28,6 +28,7 @@ GOptionContext *meta_get_option_context (void);
|
||||
void meta_init (void);
|
||||
int meta_run (void);
|
||||
void meta_register_with_session (void);
|
||||
gboolean meta_activate_session (void);
|
||||
gboolean meta_get_replace_current_wm (void); /* Actually defined in util.c */
|
||||
|
||||
void meta_set_wm_name (const char *wm_name);
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
* @META_PREF_EDGE_TILING: edge tiling
|
||||
* @META_PREF_FORCE_FULLSCREEN: force fullscreen
|
||||
* @META_PREF_WORKSPACES_ONLY_ON_PRIMARY: workspaces only on primary
|
||||
* @META_PREF_NO_TAB_POPUP: no tab popup
|
||||
* @META_PREF_DRAGGABLE_BORDER_WIDTH: draggable border width
|
||||
* @META_PREF_AUTO_MAXIMIZE: auto-maximize
|
||||
*/
|
||||
@@ -100,7 +99,6 @@ typedef enum
|
||||
META_PREF_EDGE_TILING,
|
||||
META_PREF_FORCE_FULLSCREEN,
|
||||
META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
META_PREF_DRAGGABLE_BORDER_WIDTH,
|
||||
META_PREF_AUTO_MAXIMIZE
|
||||
} MetaPreference;
|
||||
@@ -163,9 +161,6 @@ void meta_prefs_set_force_fullscreen (gboolean whether);
|
||||
|
||||
gboolean meta_prefs_get_workspaces_only_on_primary (void);
|
||||
|
||||
gboolean meta_prefs_get_no_tab_popup (void);
|
||||
void meta_prefs_set_no_tab_popup (gboolean whether);
|
||||
|
||||
int meta_prefs_get_draggable_border_width (void);
|
||||
|
||||
gboolean meta_prefs_get_ignore_request_hide_titlebar (void);
|
||||
@@ -204,8 +199,6 @@ void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
|
||||
* @META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: FILLME
|
||||
* @META_KEYBINDING_ACTION_CYCLE_PANELS: FILLME
|
||||
* @META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: FILLME
|
||||
* @META_KEYBINDING_ACTION_TAB_POPUP_SELECT: FILLME
|
||||
* @META_KEYBINDING_ACTION_TAB_POPUP_CANCEL: FILLME
|
||||
* @META_KEYBINDING_ACTION_SHOW_DESKTOP: FILLME
|
||||
* @META_KEYBINDING_ACTION_PANEL_MAIN_MENU: FILLME
|
||||
* @META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: FILLME
|
||||
@@ -301,8 +294,6 @@ typedef enum _MetaKeyBindingAction
|
||||
META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD,
|
||||
META_KEYBINDING_ACTION_CYCLE_PANELS,
|
||||
META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
|
||||
META_KEYBINDING_ACTION_TAB_POPUP_SELECT,
|
||||
META_KEYBINDING_ACTION_TAB_POPUP_CANCEL,
|
||||
META_KEYBINDING_ACTION_SHOW_DESKTOP,
|
||||
META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
|
||||
META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
|
||||
@@ -380,20 +371,6 @@ typedef enum
|
||||
META_KEY_BINDING_IS_REVERSED = 1 << 3
|
||||
} MetaKeyBindingFlags;
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyHandlerFunc:
|
||||
* @display: a #MetaDisplay
|
||||
@@ -411,45 +388,14 @@ typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *bindings;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
GType meta_key_binding_get_type (void);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
|
||||
MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name);
|
||||
|
||||
void meta_prefs_get_window_binding (const char *name,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers);
|
||||
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
gboolean meta_prefs_get_visual_bell (void);
|
||||
gboolean meta_prefs_bell_is_audible (void);
|
||||
GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
_Name=Mutter (wayland compositor)
|
||||
Exec=mutter-launch -- mutter --wayland
|
||||
Exec=mutter-launch -- mutter --wayland --display-server
|
||||
NoDisplay=true
|
||||
# name of loadable control center module
|
||||
X-GNOME-WMSettingsModule=metacity
|
||||
|
||||
@@ -2,31 +2,31 @@
|
||||
<schema id="org.gnome.mutter.wayland.keybindings" path="/org/gnome/mutter/wayland/keybindings/"
|
||||
gettext-domain="@GETTEXT_DOMAIN@">
|
||||
<key name="switch-to-session-1" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F1', 'XF86Switch_VT_1']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F1']]]></default>
|
||||
<_summary>Switch to VT 1</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-2" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F2', 'XF86Switch_VT_2']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F2']]]></default>
|
||||
<_summary>Switch to VT 2</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-3" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F3', 'XF86Switch_VT_3']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F3']]]></default>
|
||||
<_summary>Switch to VT 3</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-4" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F4', 'XF86Switch_VT_4']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F4']]]></default>
|
||||
<_summary>Switch to VT 4</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-5" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F5', 'XF86Switch_VT_5']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F5']]]></default>
|
||||
<_summary>Switch to VT 5</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-6" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F6', 'XF86Switch_VT_6']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F6']]]></default>
|
||||
<_summary>Switch to VT 6</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-7" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F7', 'XF86Switch_VT_7']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F7']]]></default>
|
||||
<_summary>Switch to VT 7</_summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Draw a workspace */
|
||||
|
||||
/* This file should not be modified to depend on other files in
|
||||
* libwnck or mutter, since it's used in both of them
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "draw-workspace.h"
|
||||
#include "theme-private.h"
|
||||
|
||||
|
||||
static void
|
||||
get_window_rect (const WnckWindowDisplayInfo *win,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
const GdkRectangle *workspace_rect,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
double width_ratio, height_ratio;
|
||||
int x, y, width, height;
|
||||
|
||||
width_ratio = (double) workspace_rect->width / (double) screen_width;
|
||||
height_ratio = (double) workspace_rect->height / (double) screen_height;
|
||||
|
||||
x = win->x;
|
||||
y = win->y;
|
||||
width = win->width;
|
||||
height = win->height;
|
||||
|
||||
x *= width_ratio;
|
||||
y *= height_ratio;
|
||||
width *= width_ratio;
|
||||
height *= height_ratio;
|
||||
|
||||
x += workspace_rect->x;
|
||||
y += workspace_rect->y;
|
||||
|
||||
if (width < 3)
|
||||
width = 3;
|
||||
if (height < 3)
|
||||
height = 3;
|
||||
|
||||
rect->x = x;
|
||||
rect->y = y;
|
||||
rect->width = width;
|
||||
rect->height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_window (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
const WnckWindowDisplayInfo *win,
|
||||
const GdkRectangle *winrect,
|
||||
GtkStateFlags state)
|
||||
{
|
||||
GdkPixbuf *icon;
|
||||
int icon_x, icon_y, icon_w, icon_h;
|
||||
gboolean is_active;
|
||||
GdkRGBA color;
|
||||
GtkStyleContext *style;
|
||||
|
||||
is_active = win->is_active;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height);
|
||||
cairo_clip (cr);
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
if (is_active)
|
||||
meta_gtk_style_get_light_color (style, state, &color);
|
||||
else
|
||||
gtk_style_context_get_background_color (style, state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
winrect->x + 1, winrect->y + 1,
|
||||
MAX (0, winrect->width - 2), MAX (0, winrect->height - 2));
|
||||
cairo_fill (cr);
|
||||
|
||||
|
||||
icon = win->icon;
|
||||
|
||||
icon_w = icon_h = 0;
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
/* If the icon is too big, fall back to mini icon.
|
||||
* We don't arbitrarily scale the icon, because it's
|
||||
* just too slow on my Athlon 850.
|
||||
*/
|
||||
if (icon_w > (winrect->width - 2) ||
|
||||
icon_h > (winrect->height - 2))
|
||||
{
|
||||
icon = win->mini_icon;
|
||||
if (icon)
|
||||
{
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
/* Give up. */
|
||||
if (icon_w > (winrect->width - 2) ||
|
||||
icon_h > (winrect->height - 2))
|
||||
icon = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon_x = winrect->x + (winrect->width - icon_w) / 2;
|
||||
icon_y = winrect->y + (winrect->height - icon_h) / 2;
|
||||
|
||||
cairo_save (cr);
|
||||
gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y);
|
||||
cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h);
|
||||
cairo_clip (cr);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
gtk_style_context_get_color (style, state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_rectangle (cr,
|
||||
winrect->x + 0.5, winrect->y + 0.5,
|
||||
MAX (0, winrect->width - 1), MAX (0, winrect->height - 1));
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
void
|
||||
wnck_draw_workspace (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
GdkPixbuf *workspace_background,
|
||||
gboolean is_active,
|
||||
const WnckWindowDisplayInfo *windows,
|
||||
int n_windows)
|
||||
{
|
||||
int i;
|
||||
GdkRectangle workspace_rect;
|
||||
GtkStateFlags state;
|
||||
GtkStyleContext *style;
|
||||
|
||||
workspace_rect.x = x;
|
||||
workspace_rect.y = y;
|
||||
workspace_rect.width = width;
|
||||
workspace_rect.height = height;
|
||||
|
||||
if (is_active)
|
||||
state = GTK_STATE_FLAG_SELECTED;
|
||||
else if (workspace_background)
|
||||
state = GTK_STATE_FLAG_PRELIGHT;
|
||||
else
|
||||
state = GTK_STATE_FLAG_NORMAL;
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
if (workspace_background)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
meta_gtk_style_get_dark_color (style,state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_rectangle (cr, x, y, width, height);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
const WnckWindowDisplayInfo *win = &windows[i];
|
||||
GdkRectangle winrect;
|
||||
|
||||
get_window_rect (win, screen_width,
|
||||
screen_height, &workspace_rect, &winrect);
|
||||
|
||||
draw_window (widget,
|
||||
cr,
|
||||
win,
|
||||
&winrect,
|
||||
state);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Draw a workspace */
|
||||
|
||||
/* This file should not be modified to depend on other files in
|
||||
* libwnck or metacity, since it's used in both of them
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WNCK_DRAW_WORKSPACE_H
|
||||
#define WNCK_DRAW_WORKSPACE_H
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
guint is_active : 1;
|
||||
|
||||
} WnckWindowDisplayInfo;
|
||||
|
||||
void wnck_draw_workspace (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
GdkPixbuf *workspace_background,
|
||||
gboolean is_active,
|
||||
const WnckWindowDisplayInfo *windows,
|
||||
int n_windows);
|
||||
|
||||
#endif
|
||||
@@ -44,8 +44,6 @@
|
||||
static void meta_frames_destroy (GtkWidget *object);
|
||||
static void meta_frames_finalize (GObject *object);
|
||||
static void meta_frames_style_updated (GtkWidget *widget);
|
||||
static void meta_frames_map (GtkWidget *widget);
|
||||
static void meta_frames_unmap (GtkWidget *widget);
|
||||
|
||||
static void meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
@@ -134,9 +132,6 @@ meta_frames_class_init (MetaFramesClass *class)
|
||||
|
||||
widget_class->style_updated = meta_frames_style_updated;
|
||||
|
||||
widget_class->map = meta_frames_map;
|
||||
widget_class->unmap = meta_frames_unmap;
|
||||
|
||||
widget_class->draw = meta_frames_draw;
|
||||
widget_class->destroy_event = meta_frames_destroy_event;
|
||||
widget_class->button_press_event = meta_frames_button_press_event;
|
||||
@@ -231,6 +226,7 @@ meta_frames_init (MetaFrames *frames)
|
||||
|
||||
frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
|
||||
update_style_contexts (frames);
|
||||
|
||||
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
|
||||
@@ -522,13 +518,26 @@ MetaFrames*
|
||||
meta_frames_new (int screen_number)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
MetaFrames *frames;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
|
||||
return g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
NULL);
|
||||
frames = g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
"type", GTK_WINDOW_POPUP,
|
||||
NULL);
|
||||
|
||||
/* Put the window at an arbitrary offscreen location; the one place
|
||||
* it can't be is at -100x-100, since the meta_window_new() will
|
||||
* mistake it for a window created via meta_create_offscreen_window()
|
||||
* and ignore it, and we need this window to get frame-synchronization
|
||||
* messages so that GTK+'s style change handling works.
|
||||
*/
|
||||
gtk_window_move (GTK_WINDOW (frames), -200, -200);
|
||||
gtk_window_resize (GTK_WINDOW (frames), 1, 1);
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
/* In order to use a style with a window it has to be attached to that
|
||||
@@ -635,22 +644,6 @@ meta_frames_unmanage_window (MetaFrames *frames,
|
||||
meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_map (GtkWidget *widget)
|
||||
{
|
||||
/* We override the parent map function to a no-op because we don't
|
||||
* want to actually show the GDK window. But GTK needs to think that
|
||||
* the widget is mapped or it won't deliver the events we care about.
|
||||
*/
|
||||
gtk_widget_set_mapped (widget, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_unmap (GtkWidget *widget)
|
||||
{
|
||||
gtk_widget_set_mapped (widget, FALSE);
|
||||
}
|
||||
|
||||
static MetaUIFrame*
|
||||
meta_frames_lookup_window (MetaFrames *frames,
|
||||
Window xwindow)
|
||||
|
||||
@@ -1,963 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter popup window thing showing windows you can tab to */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2002 Red Hat, Inc.
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/util.h>
|
||||
#include "core.h"
|
||||
#include "tabpopup.h"
|
||||
/* FIXME these two includes are 100% broken ...
|
||||
*/
|
||||
#include "workspace-private.h"
|
||||
#include "frame.h"
|
||||
#include "draw-workspace.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <math.h>
|
||||
|
||||
#define OUTSIDE_SELECT_RECT 2
|
||||
#define INSIDE_SELECT_RECT 2
|
||||
|
||||
typedef struct _TabEntry TabEntry;
|
||||
|
||||
struct _TabEntry
|
||||
{
|
||||
MetaTabEntryKey key;
|
||||
char *title;
|
||||
GdkPixbuf *icon, *dimmed_icon;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle rect;
|
||||
GdkRectangle inner_rect;
|
||||
guint blank : 1;
|
||||
};
|
||||
|
||||
struct _MetaTabPopup
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *label;
|
||||
GList *current;
|
||||
GList *entries;
|
||||
TabEntry *current_selected_entry;
|
||||
GtkWidget *outline_window;
|
||||
gboolean outline;
|
||||
};
|
||||
|
||||
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
|
||||
static void select_image (GtkWidget *widget);
|
||||
static void unselect_image (GtkWidget *widget);
|
||||
|
||||
static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace);
|
||||
static void select_workspace (GtkWidget *widget);
|
||||
static void unselect_workspace (GtkWidget *widget);
|
||||
|
||||
static gboolean
|
||||
outline_window_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gpointer data)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
TabEntry *te;
|
||||
|
||||
popup = data;
|
||||
|
||||
if (!popup->outline || popup->current_selected_entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
te = popup->current_selected_entry;
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
0.5, 0.5,
|
||||
te->rect.width - 1,
|
||||
te->rect.height - 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
te->inner_rect.x - 0.5, te->inner_rect.y - 0.5,
|
||||
te->inner_rect.width + 1,
|
||||
te->inner_rect.height + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
dimm_icon (GdkPixbuf *pixbuf)
|
||||
{
|
||||
int x, y, pixel_stride, row_stride;
|
||||
guchar *row, *pixels;
|
||||
int w, h;
|
||||
GdkPixbuf *dimmed_pixbuf;
|
||||
|
||||
if (gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
dimmed_pixbuf = gdk_pixbuf_copy (pixbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
}
|
||||
|
||||
w = gdk_pixbuf_get_width (dimmed_pixbuf);
|
||||
h = gdk_pixbuf_get_height (dimmed_pixbuf);
|
||||
|
||||
pixel_stride = 4;
|
||||
|
||||
row = gdk_pixbuf_get_pixels (dimmed_pixbuf);
|
||||
row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf);
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
pixels = row;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixels[3] /= 2;
|
||||
pixels += pixel_stride;
|
||||
}
|
||||
row += row_stride;
|
||||
}
|
||||
return dimmed_pixbuf;
|
||||
}
|
||||
|
||||
static TabEntry*
|
||||
tab_entry_new (const MetaTabEntry *entry,
|
||||
gint screen_width,
|
||||
gboolean outline)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = g_new (TabEntry, 1);
|
||||
te->key = entry->key;
|
||||
te->title = NULL;
|
||||
if (entry->title)
|
||||
{
|
||||
gchar *str;
|
||||
gchar *tmp;
|
||||
gchar *formatter = "%s";
|
||||
|
||||
str = meta_g_utf8_strndup (entry->title, 4096);
|
||||
|
||||
if (entry->hidden)
|
||||
{
|
||||
formatter = "[%s]";
|
||||
}
|
||||
|
||||
tmp = g_markup_printf_escaped (formatter, str);
|
||||
g_free (str);
|
||||
str = tmp;
|
||||
|
||||
if (entry->demands_attention)
|
||||
{
|
||||
/* Escape the whole line of text then markup the text and
|
||||
* copy it back into the original buffer.
|
||||
*/
|
||||
tmp = g_strdup_printf ("<b>%s</b>", str);
|
||||
g_free (str);
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
te->title=g_strdup(str);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
te->widget = NULL;
|
||||
te->icon = entry->icon;
|
||||
te->blank = entry->blank;
|
||||
te->dimmed_icon = NULL;
|
||||
if (te->icon)
|
||||
{
|
||||
g_object_ref (G_OBJECT (te->icon));
|
||||
if (entry->hidden)
|
||||
te->dimmed_icon = dimm_icon (entry->icon);
|
||||
}
|
||||
|
||||
if (outline)
|
||||
{
|
||||
te->rect.x = entry->rect.x;
|
||||
te->rect.y = entry->rect.y;
|
||||
te->rect.width = entry->rect.width;
|
||||
te->rect.height = entry->rect.height;
|
||||
|
||||
te->inner_rect.x = entry->inner_rect.x;
|
||||
te->inner_rect.y = entry->inner_rect.y;
|
||||
te->inner_rect.width = entry->inner_rect.width;
|
||||
te->inner_rect.height = entry->inner_rect.height;
|
||||
}
|
||||
return te;
|
||||
}
|
||||
|
||||
MetaTabPopup*
|
||||
meta_ui_tab_popup_new (const MetaTabEntry *entries,
|
||||
int screen_number,
|
||||
int entry_count,
|
||||
int width,
|
||||
gboolean outline)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
int i, left, top;
|
||||
int height;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *align;
|
||||
GList *tmp;
|
||||
GtkWidget *frame;
|
||||
int max_label_width; /* the actual max width of the labels we create */
|
||||
AtkObject *obj;
|
||||
GdkScreen *screen;
|
||||
int screen_width;
|
||||
|
||||
popup = g_new (MetaTabPopup, 1);
|
||||
|
||||
popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
gtk_window_set_screen (GTK_WINDOW (popup->outline_window),
|
||||
screen);
|
||||
|
||||
gtk_widget_set_app_paintable (popup->outline_window, TRUE);
|
||||
gtk_widget_realize (popup->outline_window);
|
||||
|
||||
g_signal_connect (G_OBJECT (popup->outline_window), "draw",
|
||||
G_CALLBACK (outline_window_draw), popup);
|
||||
|
||||
popup->window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (popup->window),
|
||||
screen);
|
||||
|
||||
gtk_window_set_position (GTK_WINDOW (popup->window),
|
||||
GTK_WIN_POS_CENTER_ALWAYS);
|
||||
/* enable resizing, to get never-shrink behavior */
|
||||
gtk_window_set_resizable (GTK_WINDOW (popup->window),
|
||||
TRUE);
|
||||
popup->current = NULL;
|
||||
popup->entries = NULL;
|
||||
popup->current_selected_entry = NULL;
|
||||
popup->outline = outline;
|
||||
|
||||
screen_width = gdk_screen_get_width (screen);
|
||||
for (i = 0; i < entry_count; ++i)
|
||||
{
|
||||
TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline);
|
||||
popup->entries = g_list_prepend (popup->entries, new_entry);
|
||||
}
|
||||
|
||||
popup->entries = g_list_reverse (popup->entries);
|
||||
|
||||
g_assert (width > 0);
|
||||
height = i / width;
|
||||
if (i % width)
|
||||
height += 1;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (grid), 1);
|
||||
gtk_container_add (GTK_CONTAINER (popup->window),
|
||||
frame);
|
||||
gtk_container_add (GTK_CONTAINER (frame),
|
||||
vbox);
|
||||
|
||||
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (align),
|
||||
grid);
|
||||
|
||||
popup->label = gtk_label_new ("");
|
||||
|
||||
/* Set the accessible role of the label to a status bar so it
|
||||
* will emit name changed events that can be used by screen
|
||||
* readers.
|
||||
*/
|
||||
obj = gtk_widget_get_accessible (popup->label);
|
||||
atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
|
||||
|
||||
gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
|
||||
|
||||
max_label_width = 0;
|
||||
top = 0;
|
||||
tmp = popup->entries;
|
||||
|
||||
while (tmp && top < height)
|
||||
{
|
||||
left = 0;
|
||||
|
||||
while (tmp && left < width)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GtkRequisition req;
|
||||
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->blank)
|
||||
{
|
||||
/* just stick a widget here to avoid special cases */
|
||||
image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else if (outline)
|
||||
{
|
||||
if (te->dimmed_icon)
|
||||
{
|
||||
image = selectable_image_new (te->dimmed_icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = selectable_image_new (te->icon);
|
||||
}
|
||||
|
||||
gtk_misc_set_padding (GTK_MISC (image),
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1,
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1);
|
||||
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = selectable_workspace_new ((MetaWorkspace *) te->key);
|
||||
}
|
||||
|
||||
te->widget = image;
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
te->widget,
|
||||
left, top, 1, 1);
|
||||
|
||||
/* Efficiency rules! */
|
||||
gtk_label_set_markup (GTK_LABEL (popup->label),
|
||||
te->title);
|
||||
gtk_widget_get_preferred_size (popup->label, &req, NULL);
|
||||
max_label_width = MAX (max_label_width, req.width);
|
||||
|
||||
tmp = tmp->next;
|
||||
|
||||
++left;
|
||||
}
|
||||
|
||||
++top;
|
||||
}
|
||||
|
||||
/* remove all the temporary text */
|
||||
gtk_label_set_text (GTK_LABEL (popup->label), "");
|
||||
/* Make it so that we ellipsize if the text is too long */
|
||||
gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END);
|
||||
|
||||
/* Limit the window size to no bigger than screen_width/4 */
|
||||
if (max_label_width>(screen_width/4))
|
||||
{
|
||||
max_label_width = screen_width/4;
|
||||
}
|
||||
|
||||
max_label_width += 20; /* add random padding */
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (popup->window),
|
||||
max_label_width,
|
||||
-1);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
static void
|
||||
free_tab_entry (gpointer data, gpointer user_data)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = data;
|
||||
|
||||
g_free (te->title);
|
||||
if (te->icon)
|
||||
g_object_unref (G_OBJECT (te->icon));
|
||||
if (te->dimmed_icon)
|
||||
g_object_unref (G_OBJECT (te->dimmed_icon));
|
||||
|
||||
g_free (te);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_free (MetaTabPopup *popup)
|
||||
{
|
||||
meta_verbose ("Destroying tab popup window\n");
|
||||
|
||||
if (!popup)
|
||||
{
|
||||
meta_warning ("NULL passed to meta_ui_tab_popup_free\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_destroy (popup->outline_window);
|
||||
gtk_widget_destroy (popup->window);
|
||||
|
||||
g_list_foreach (popup->entries, free_tab_entry, NULL);
|
||||
|
||||
g_list_free (popup->entries);
|
||||
|
||||
g_free (popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing)
|
||||
{
|
||||
if (showing)
|
||||
{
|
||||
gtk_widget_show_all (popup->window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_widget_get_visible (popup->window))
|
||||
{
|
||||
meta_verbose ("Hiding tab popup window\n");
|
||||
gtk_widget_hide (popup->window);
|
||||
meta_core_increment_event_serial (
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_entry (MetaTabPopup *popup,
|
||||
TabEntry *te)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GdkWindow *window;
|
||||
|
||||
|
||||
if (popup->current_selected_entry)
|
||||
{
|
||||
if (popup->outline)
|
||||
unselect_image (popup->current_selected_entry->widget);
|
||||
else
|
||||
unselect_workspace (popup->current_selected_entry->widget);
|
||||
}
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (popup->label), te->title);
|
||||
|
||||
if (popup->outline)
|
||||
select_image (te->widget);
|
||||
else
|
||||
select_workspace (te->widget);
|
||||
|
||||
if (popup->outline)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
cairo_region_t *inner_region;
|
||||
GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
window = gtk_widget_get_window (popup->outline_window);
|
||||
|
||||
/* Do stuff behind gtk's back */
|
||||
gdk_window_hide (window);
|
||||
meta_core_increment_event_serial (
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
|
||||
rect = te->rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
|
||||
gdk_window_move_resize (window,
|
||||
te->rect.x, te->rect.y,
|
||||
te->rect.width, te->rect.height);
|
||||
|
||||
gdk_window_set_background_rgba (window, &black);
|
||||
|
||||
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
inner_region = cairo_region_create_rectangle (&te->inner_rect);
|
||||
cairo_region_subtract (region, inner_region);
|
||||
cairo_region_destroy (inner_region);
|
||||
|
||||
gdk_window_shape_combine_region (window,
|
||||
region,
|
||||
0, 0);
|
||||
|
||||
cairo_region_destroy (region);
|
||||
|
||||
|
||||
/* This should piss off gtk a bit, but we don't want to raise
|
||||
* above the tab popup. So, instead of calling gtk_widget_show,
|
||||
* we manually set the window as mapped and then manually map it
|
||||
* with gdk functions.
|
||||
*/
|
||||
gtk_widget_set_mapped (popup->outline_window, TRUE);
|
||||
gdk_window_show_unraised (window);
|
||||
}
|
||||
|
||||
/* Must be before we handle an expose for the outline window */
|
||||
popup->current_selected_entry = te;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_forward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->next;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = popup->entries;
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_backward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->prev;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = g_list_last (popup->entries);
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
MetaTabEntryKey
|
||||
meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
return te->key;
|
||||
}
|
||||
else
|
||||
return (MetaTabEntryKey)None;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
MetaTabEntryKey key)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
/* Note, "key" may not be in the list of entries; other code assumes
|
||||
* it's OK to pass in a key that isn't.
|
||||
*/
|
||||
|
||||
tmp = popup->entries;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->key == key)
|
||||
{
|
||||
popup->current = tmp;
|
||||
|
||||
display_entry (popup, te);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ())
|
||||
#define META_SELECT_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage))
|
||||
|
||||
typedef struct _MetaSelectImage MetaSelectImage;
|
||||
typedef struct _MetaSelectImageClass MetaSelectImageClass;
|
||||
|
||||
struct _MetaSelectImage
|
||||
{
|
||||
GtkImage parent_instance;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectImageClass
|
||||
{
|
||||
GtkImageClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_image_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GtkWidget*
|
||||
selectable_image_new (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
w = g_object_new (meta_select_image_get_type (), NULL);
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
select_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_image_class_init (MetaSelectImageClass *klass);
|
||||
static gboolean meta_select_image_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
|
||||
static GtkImageClass *parent_class;
|
||||
|
||||
GType
|
||||
meta_select_image_get_type (void)
|
||||
{
|
||||
static GType image_type = 0;
|
||||
|
||||
if (!image_type)
|
||||
{
|
||||
static const GTypeInfo image_info =
|
||||
{
|
||||
sizeof (MetaSelectImageClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_image_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectImage),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0);
|
||||
}
|
||||
|
||||
return image_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_image_class_init (MetaSelectImageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
parent_class = g_type_class_peek (gtk_image_get_type ());
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->draw = meta_select_image_draw;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_select_image_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (META_SELECT_IMAGE (widget)->selected)
|
||||
{
|
||||
GtkMisc *misc;
|
||||
GtkRequisition requisition;
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
int x, y, w, h;
|
||||
gint xpad, ypad;
|
||||
gfloat xalign, yalign;
|
||||
|
||||
misc = GTK_MISC (widget);
|
||||
|
||||
gtk_widget_get_requisition (widget, &requisition);
|
||||
gtk_misc_get_alignment (misc, &xalign, &yalign);
|
||||
gtk_misc_get_padding (misc, &xpad, &ypad);
|
||||
|
||||
x = (allocation.width - (requisition.width - xpad * 2)) * xalign + 0.5;
|
||||
y = (allocation.height - (requisition.height - ypad * 2)) * yalign + 0.5;
|
||||
|
||||
x -= INSIDE_SELECT_RECT + 1;
|
||||
y -= INSIDE_SELECT_RECT + 1;
|
||||
|
||||
w = requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
h = requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_set_state (context,
|
||||
gtk_widget_get_state_flags (widget));
|
||||
|
||||
gtk_style_context_lookup_color (context, "color", &color);
|
||||
|
||||
cairo_set_line_width (cr, 2.0);
|
||||
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
|
||||
|
||||
cairo_rectangle (cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
}
|
||||
|
||||
return GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ())
|
||||
#define META_SELECT_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace))
|
||||
|
||||
typedef struct _MetaSelectWorkspace MetaSelectWorkspace;
|
||||
typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass;
|
||||
|
||||
struct _MetaSelectWorkspace
|
||||
{
|
||||
GtkDrawingArea parent_instance;
|
||||
MetaWorkspace *workspace;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectWorkspaceClass
|
||||
{
|
||||
GtkDrawingAreaClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_workspace_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#define SELECT_OUTLINE_WIDTH 2
|
||||
#define MINI_WORKSPACE_WIDTH 48
|
||||
|
||||
static GtkWidget*
|
||||
selectable_workspace_new (MetaWorkspace *workspace)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
double screen_aspect;
|
||||
|
||||
widget = g_object_new (meta_select_workspace_get_type (), NULL);
|
||||
|
||||
screen_aspect = (double) workspace->screen->rect.height /
|
||||
(double) workspace->screen->rect.width;
|
||||
|
||||
/* account for select rect */
|
||||
gtk_widget_set_size_request (widget,
|
||||
MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2,
|
||||
MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2);
|
||||
|
||||
META_SELECT_WORKSPACE (widget)->workspace = workspace;
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void
|
||||
select_workspace (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_WORKSPACE(widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_workspace (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_WORKSPACE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass);
|
||||
|
||||
static gboolean meta_select_workspace_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
|
||||
GType
|
||||
meta_select_workspace_get_type (void)
|
||||
{
|
||||
static GType workspace_type = 0;
|
||||
|
||||
if (!workspace_type)
|
||||
{
|
||||
static const GTypeInfo workspace_info =
|
||||
{
|
||||
sizeof (MetaSelectWorkspaceClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_workspace_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectWorkspace),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
|
||||
"MetaSelectWorkspace",
|
||||
&workspace_info,
|
||||
0);
|
||||
}
|
||||
|
||||
return workspace_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->draw = meta_select_workspace_draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_convert_meta_to_wnck:
|
||||
* @window: the #MetaWindow
|
||||
* @screen: the #MetaScreen the window is on
|
||||
*
|
||||
* Converts a #MetaWindow to a #WnckWindowDisplayInfo window
|
||||
* that is used to build a thumbnail of a workspace.
|
||||
**/
|
||||
static WnckWindowDisplayInfo
|
||||
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
||||
{
|
||||
WnckWindowDisplayInfo wnck_window;
|
||||
wnck_window.icon = window->icon;
|
||||
wnck_window.mini_icon = window->mini_icon;
|
||||
wnck_window.is_active = window->has_focus;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
wnck_window.x = window->frame->rect.x;
|
||||
wnck_window.y = window->frame->rect.y;
|
||||
wnck_window.width = window->frame->rect.width;
|
||||
wnck_window.height = window->frame->rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
wnck_window.x = window->rect.x;
|
||||
wnck_window.y = window->rect.y;
|
||||
wnck_window.width = window->rect.width;
|
||||
wnck_window.height = window->rect.height;
|
||||
}
|
||||
return wnck_window;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
meta_select_workspace_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
WnckWindowDisplayInfo *windows;
|
||||
GtkAllocation allocation;
|
||||
int i, n_windows;
|
||||
GList *tmp, *list;
|
||||
|
||||
workspace = META_SELECT_WORKSPACE (widget)->workspace;
|
||||
|
||||
list = meta_stack_list_windows (workspace->screen->stack, workspace);
|
||||
n_windows = g_list_length (list);
|
||||
windows = g_new (WnckWindowDisplayInfo, n_windows);
|
||||
|
||||
tmp = list;
|
||||
i = 0;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *window;
|
||||
gboolean ignoreable_sticky;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
ignoreable_sticky = window->on_all_workspaces &&
|
||||
workspace != workspace->screen->active_workspace;
|
||||
|
||||
if (window->skip_pager ||
|
||||
!meta_window_showing_on_its_workspace (window) ||
|
||||
window->unmaps_pending ||
|
||||
ignoreable_sticky)
|
||||
{
|
||||
--n_windows;
|
||||
}
|
||||
else
|
||||
{
|
||||
windows[i] = meta_convert_meta_to_wnck (window, workspace->screen);
|
||||
i++;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
wnck_draw_workspace (widget,
|
||||
cr,
|
||||
SELECT_OUTLINE_WIDTH,
|
||||
SELECT_OUTLINE_WIDTH,
|
||||
allocation.width - SELECT_OUTLINE_WIDTH * 2,
|
||||
allocation.height - SELECT_OUTLINE_WIDTH * 2,
|
||||
workspace->screen->rect.width,
|
||||
workspace->screen->rect.height,
|
||||
NULL,
|
||||
(workspace->screen->active_workspace == workspace),
|
||||
windows,
|
||||
n_windows);
|
||||
|
||||
g_free (windows);
|
||||
|
||||
if (META_SELECT_WORKSPACE (widget)->selected)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_set_state (context,
|
||||
gtk_widget_get_state_flags (widget));
|
||||
|
||||
gtk_style_context_lookup_color (context, "color", &color);
|
||||
|
||||
cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH);
|
||||
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0,
|
||||
allocation.width - SELECT_OUTLINE_WIDTH,
|
||||
allocation.height - SELECT_OUTLINE_WIDTH);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter tab popup window */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef META_TABPOPUP_H
|
||||
#define META_TABPOPUP_H
|
||||
|
||||
/* Don't include gtk.h or gdk.h here */
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct _MetaTabEntry MetaTabEntry;
|
||||
typedef struct _MetaTabPopup MetaTabPopup;
|
||||
typedef void *MetaTabEntryKey;
|
||||
|
||||
struct _MetaTabEntry
|
||||
{
|
||||
MetaTabEntryKey key;
|
||||
const char *title;
|
||||
GdkPixbuf *icon;
|
||||
MetaRectangle rect;
|
||||
MetaRectangle inner_rect;
|
||||
guint blank : 1;
|
||||
guint hidden : 1;
|
||||
guint demands_attention : 1;
|
||||
};
|
||||
|
||||
MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
|
||||
int screen_number,
|
||||
int entry_count,
|
||||
int width,
|
||||
gboolean outline);
|
||||
void meta_ui_tab_popup_free (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing);
|
||||
void meta_ui_tab_popup_forward (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_backward (MetaTabPopup *popup);
|
||||
MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
MetaTabEntryKey key);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
80
src/ui/ui.c
80
src/ui/ui.c
@@ -295,9 +295,12 @@ meta_ui_new (Display *xdisplay,
|
||||
g_assert (gdisplay == gdk_display_get_default ());
|
||||
|
||||
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
|
||||
/* This does not actually show any widget. MetaFrames has been hacked so
|
||||
* that showing it doesn't actually do anything. But we need the flags
|
||||
* set for GTK to deliver events properly. */
|
||||
/* GTK+ needs the frame-sync protocol to work in order to properly
|
||||
* handle style changes. This means that the dummy widget we create
|
||||
* to get the style for title bars actually needs to be mapped
|
||||
* and fully tracked as a MetaWindow. Horrible, but mostly harmless -
|
||||
* the window is a 1x1 overide redirect window positioned offscreen.
|
||||
*/
|
||||
gtk_widget_show (GTK_WIDGET (ui->frames));
|
||||
|
||||
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
|
||||
@@ -595,76 +598,6 @@ meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
|
||||
return retval;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_ui_get_default_window_icon (MetaUI *ui)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
gboolean icon_exists;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
|
||||
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
|
||||
|
||||
if (icon_exists)
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
META_DEFAULT_ICON_NAME,
|
||||
META_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
else
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
"image-missing",
|
||||
META_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
g_object_ref (G_OBJECT (default_icon));
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_ui_get_default_mini_icon (MetaUI *ui)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
gboolean icon_exists;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
|
||||
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
|
||||
|
||||
if (icon_exists)
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
META_DEFAULT_ICON_NAME,
|
||||
META_MINI_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
else
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
"image-missing",
|
||||
META_MINI_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
g_object_ref (G_OBJECT (default_icon));
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow)
|
||||
@@ -772,7 +705,6 @@ void
|
||||
meta_ui_set_current_theme (const char *name)
|
||||
{
|
||||
meta_theme_set_current (name);
|
||||
meta_invalidate_default_icons ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -143,9 +143,6 @@ GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
|
||||
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
|
||||
|
||||
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow);
|
||||
|
||||
@@ -178,6 +175,4 @@ int meta_ui_get_drag_threshold (MetaUI *ui);
|
||||
|
||||
MetaUIDirection meta_ui_get_direction (void);
|
||||
|
||||
#include "tabpopup.h"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,7 +48,7 @@ data_offer_accept (struct wl_client *client,
|
||||
* this be a wl_data_device request? */
|
||||
|
||||
if (offer->source)
|
||||
offer->source->accept (offer->source, serial, mime_type);
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -58,9 +58,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
offer->source->send (offer->source, mime_type, fd);
|
||||
else
|
||||
close (fd);
|
||||
wl_data_source_send_send (offer->source->resource, mime_type, fd);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -82,7 +82,8 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
|
||||
if (offer->source)
|
||||
wl_list_remove (&offer->source_destroy_listener.link);
|
||||
free (offer);
|
||||
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -99,13 +100,9 @@ static struct wl_resource *
|
||||
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
char **p;
|
||||
|
||||
offer = malloc (sizeof *offer);
|
||||
if (offer == NULL)
|
||||
return NULL;
|
||||
|
||||
offer->source = source;
|
||||
offer->source_destroy_listener.notify = destroy_offer_data_source;
|
||||
|
||||
@@ -318,8 +315,12 @@ data_device_start_drag (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
/* FIXME: Check that client has implicit grab on the origin
|
||||
* surface that matches the given time. */
|
||||
|
||||
if ((seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
!seat->pointer.focus_surface ||
|
||||
seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource)))
|
||||
return;
|
||||
|
||||
/* FIXME: Check that the data source type array isn't empty. */
|
||||
|
||||
@@ -332,6 +333,7 @@ data_device_start_drag (struct wl_client *client,
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
|
||||
drag_grab->drag_client = client;
|
||||
drag_grab->seat = seat;
|
||||
|
||||
if (source_resource)
|
||||
{
|
||||
@@ -375,7 +377,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial)
|
||||
@@ -389,7 +391,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
|
||||
if (seat->selection_data_source)
|
||||
{
|
||||
seat->selection_data_source->cancel (seat->selection_data_source);
|
||||
wl_data_source_send_cancelled (seat->selection_data_source->resource);
|
||||
wl_list_remove (&seat->selection_data_source_listener.link);
|
||||
seat->selection_data_source = NULL;
|
||||
}
|
||||
@@ -449,47 +451,21 @@ static const struct wl_data_device_interface data_device_interface = {
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_container_of (resource, source, resource);
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
char **p;
|
||||
|
||||
wl_array_for_each (p, &source->mime_types) free (*p);
|
||||
|
||||
wl_array_release (&source->mime_types);
|
||||
}
|
||||
|
||||
static void
|
||||
client_source_accept (MetaWaylandDataSource *source,
|
||||
guint32 time, const char *mime_type)
|
||||
{
|
||||
wl_data_source_send_target (source->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
client_source_send (MetaWaylandDataSource *source,
|
||||
const char *mime_type, int32_t fd)
|
||||
{
|
||||
wl_data_source_send_send (source->resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
client_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
wl_data_source_send_cancelled (source->resource);
|
||||
g_slice_free (MetaWaylandDataSource, source);
|
||||
}
|
||||
|
||||
static void
|
||||
create_data_source (struct wl_client *client,
|
||||
struct wl_resource *resource, guint32 id)
|
||||
{
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
source = malloc (sizeof *source);
|
||||
if (source == NULL)
|
||||
{
|
||||
wl_resource_post_no_memory (resource);
|
||||
return;
|
||||
}
|
||||
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
|
||||
|
||||
source->resource = wl_resource_create (client, &wl_data_source_interface,
|
||||
MIN (META_WL_DATA_SOURCE_VERSION,
|
||||
@@ -497,10 +473,6 @@ create_data_source (struct wl_client *client,
|
||||
wl_resource_set_implementation (source->resource, &data_source_interface,
|
||||
source, destroy_data_source);
|
||||
|
||||
source->accept = client_source_accept;
|
||||
source->send = client_source_send;
|
||||
source->cancel = client_source_cancel;
|
||||
|
||||
wl_array_init (&source->mime_types);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,4 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
|
||||
int
|
||||
meta_wayland_data_device_manager_init (struct wl_display *display);
|
||||
|
||||
void
|
||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
MetaWaylandDataSource *source,
|
||||
uint32_t serial);
|
||||
|
||||
|
||||
#endif /* __META_WAYLAND_DATA_DEVICE_H__ */
|
||||
|
||||
@@ -142,20 +142,6 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
||||
xkb_keymap_unref (xkb_info->keymap);
|
||||
xkb_info->keymap = keymap;
|
||||
|
||||
xkb_info->shift_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
|
||||
xkb_info->caps_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CAPS);
|
||||
xkb_info->ctrl_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CTRL);
|
||||
xkb_info->alt_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_ALT);
|
||||
xkb_info->mod2_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod2");
|
||||
xkb_info->mod3_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod3");
|
||||
xkb_info->super_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_LOGO);
|
||||
xkb_info->mod5_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod5");
|
||||
|
||||
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
|
||||
if (keymap_str == NULL)
|
||||
{
|
||||
@@ -222,7 +208,6 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
|
||||
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
keyboard->focus_surface = NULL;
|
||||
|
||||
if (keyboard->focus_resource)
|
||||
@@ -237,7 +222,6 @@ keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
|
||||
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
keyboard->focus_resource = NULL;
|
||||
}
|
||||
|
||||
@@ -297,31 +281,6 @@ static const MetaWaylandKeyboardGrabInterface
|
||||
default_grab_modifiers,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
modal_key (MetaWaylandKeyboardGrab *grab,
|
||||
uint32_t time,
|
||||
uint32_t key,
|
||||
uint32_t state)
|
||||
{
|
||||
/* FALSE means: let the event through to clutter */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
modal_modifiers (MetaWaylandKeyboardGrab *grab,
|
||||
uint32_t serial,
|
||||
uint32_t mods_depressed,
|
||||
uint32_t mods_latched,
|
||||
uint32_t mods_locked,
|
||||
uint32_t group)
|
||||
{
|
||||
}
|
||||
|
||||
static MetaWaylandKeyboardGrabInterface modal_grab = {
|
||||
modal_key,
|
||||
modal_modifiers,
|
||||
};
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_display *display)
|
||||
@@ -537,26 +496,13 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
/* If we're in a modal grab, the client is focused but doesn't see
|
||||
modifiers or pressed keys (and fix that up when we exit the modal) */
|
||||
if (keyboard->grab->interface == &modal_grab)
|
||||
{
|
||||
struct wl_array empty;
|
||||
wl_array_init (&empty);
|
||||
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial, 0, 0, 0, 0);
|
||||
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource, &empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
|
||||
&keyboard->keys);
|
||||
}
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
|
||||
&keyboard->keys);
|
||||
|
||||
wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
|
||||
keyboard->focus_serial = serial;
|
||||
@@ -590,85 +536,6 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
||||
wl_array_release (&keyboard->keys);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandKeyboardGrab *grab;
|
||||
uint32_t *end = (void *) ((char *) keyboard->keys.data +
|
||||
keyboard->keys.size);
|
||||
uint32_t *k;
|
||||
uint32_t serial;
|
||||
|
||||
meta_verbose ("Asked to acquire modal keyboard grab, timestamp %d\n", timestamp);
|
||||
|
||||
if (keyboard->grab != &keyboard->default_grab)
|
||||
return FALSE;
|
||||
|
||||
if (keyboard->focus_surface)
|
||||
{
|
||||
/* Fake key release events for the focused app */
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
keyboard->grab->interface->modifiers (keyboard->grab,
|
||||
serial,
|
||||
0, 0, 0, 0);
|
||||
|
||||
for (k = keyboard->keys.data; k < end; k++)
|
||||
{
|
||||
keyboard->grab->interface->key (keyboard->grab,
|
||||
timestamp,
|
||||
*k, 0);
|
||||
}
|
||||
}
|
||||
|
||||
grab = g_slice_new0 (MetaWaylandKeyboardGrab);
|
||||
grab->interface = &modal_grab;
|
||||
meta_wayland_keyboard_start_grab (keyboard, grab);
|
||||
|
||||
meta_verbose ("Acquired modal keyboard grab, timestamp %d\n", timestamp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandKeyboardGrab *grab;
|
||||
uint32_t *end = (void *) ((char *) keyboard->keys.data +
|
||||
keyboard->keys.size);
|
||||
uint32_t *k;
|
||||
uint32_t serial;
|
||||
|
||||
grab = keyboard->grab;
|
||||
|
||||
g_assert (grab->interface == &modal_grab);
|
||||
|
||||
meta_wayland_keyboard_end_grab (keyboard);
|
||||
g_slice_free (MetaWaylandKeyboardGrab, grab);
|
||||
|
||||
if (keyboard->focus_surface)
|
||||
{
|
||||
/* Fake key press events for the focused app */
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
keyboard->grab->interface->modifiers (keyboard->grab,
|
||||
serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
|
||||
for (k = keyboard->keys.data; k < end; k++)
|
||||
{
|
||||
keyboard->grab->interface->key (keyboard->grab,
|
||||
timestamp,
|
||||
*k, 1);
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
|
||||
const char *rules,
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct _MetaWaylandKeyboardGrabInterface
|
||||
{
|
||||
@@ -71,14 +72,6 @@ typedef struct
|
||||
int keymap_fd;
|
||||
size_t keymap_size;
|
||||
char *keymap_area;
|
||||
xkb_mod_index_t shift_mod;
|
||||
xkb_mod_index_t caps_mod;
|
||||
xkb_mod_index_t ctrl_mod;
|
||||
xkb_mod_index_t alt_mod;
|
||||
xkb_mod_index_t mod2_mod;
|
||||
xkb_mod_index_t mod3_mod;
|
||||
xkb_mod_index_t super_mod;
|
||||
xkb_mod_index_t mod5_mod;
|
||||
} MetaWaylandXkbInfo;
|
||||
|
||||
typedef struct
|
||||
@@ -149,13 +142,6 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device,
|
||||
void
|
||||
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp);
|
||||
void
|
||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp);
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "xdg-shell-server-protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -60,7 +59,6 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
pointer->focus_surface = NULL;
|
||||
|
||||
if (pointer->focus_resource)
|
||||
@@ -75,7 +73,6 @@ pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
|
||||
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
|
||||
@@ -401,61 +398,6 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
||||
interface->focus (pointer->grab, pointer->current, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
modal_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
modal_motion (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
modal_button (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static MetaWaylandPointerGrabInterface modal_grab = {
|
||||
modal_focus,
|
||||
modal_motion,
|
||||
modal_button
|
||||
};
|
||||
|
||||
gboolean
|
||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaWaylandPointerGrab *grab;
|
||||
|
||||
if (pointer->grab != &pointer->default_grab)
|
||||
return FALSE;
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
|
||||
grab = g_slice_new0 (MetaWaylandPointerGrab);
|
||||
grab->interface = &modal_grab;
|
||||
meta_wayland_pointer_start_grab (pointer, grab);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaWaylandPointerGrab *grab;
|
||||
|
||||
grab = pointer->grab;
|
||||
|
||||
g_assert (grab->interface == &modal_grab);
|
||||
|
||||
meta_wayland_pointer_end_grab (pointer);
|
||||
g_slice_free (MetaWaylandPointerGrab, grab);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
MetaWaylandPointerGrab generic;
|
||||
|
||||
@@ -530,19 +472,18 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
||||
|
||||
wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_popup = &popup->surface->xdg_popup;
|
||||
struct wl_client *client = wl_resource_get_client (xdg_popup->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial;
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
xdg_popup_send_popup_done (xdg_popup->resource, serial);
|
||||
meta_wayland_surface_popup_done (popup->surface);
|
||||
wl_list_remove (&popup->surface_destroy_listener.link);
|
||||
wl_list_remove (&popup->link);
|
||||
g_slice_free (MetaWaylandPopup, popup);
|
||||
}
|
||||
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
meta_display_end_grab_op (display,
|
||||
meta_display_get_current_time_roundtrip (display));
|
||||
}
|
||||
|
||||
meta_wayland_pointer_end_grab (pointer);
|
||||
g_slice_free (MetaWaylandPopupGrab, popup_grab);
|
||||
}
|
||||
@@ -582,6 +523,8 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
|
||||
if (pointer->grab == &pointer->default_grab)
|
||||
{
|
||||
MetaWindow *window = surface->window;
|
||||
|
||||
grab = g_slice_new0 (MetaWaylandPopupGrab);
|
||||
grab->generic.interface = &popup_grab_interface;
|
||||
grab->generic.pointer = pointer;
|
||||
@@ -589,6 +532,19 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
wl_list_init (&grab->all_popups);
|
||||
|
||||
meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab);
|
||||
|
||||
meta_display_begin_grab_op (window->display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_WAYLAND_CLIENT,
|
||||
FALSE, /* pointer_already_grabbed */
|
||||
FALSE, /* frame_action */
|
||||
1, /* button. XXX? */
|
||||
0, /* modmask */
|
||||
meta_display_get_current_time_roundtrip (window->display),
|
||||
wl_fixed_to_int (pointer->grab_x),
|
||||
wl_fixed_to_int (pointer->grab_y));
|
||||
|
||||
}
|
||||
else
|
||||
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
||||
@@ -597,10 +553,12 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
popup->grab = grab;
|
||||
popup->surface = surface;
|
||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
if (surface->xdg_popup.resource)
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
|
||||
|
||||
wl_list_insert (&grab->all_popups, &popup->link);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,11 +85,6 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
gboolean
|
||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer);
|
||||
void
|
||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer);
|
||||
|
||||
gboolean
|
||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *popup);
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#define META_WAYLAND_PRIVATE_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <glib.h>
|
||||
@@ -31,7 +30,7 @@
|
||||
#include "meta-weston-launch.h"
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-versions.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
@@ -91,30 +90,8 @@ struct _MetaWaylandCompositor
|
||||
MetaWaylandSeat *seat;
|
||||
};
|
||||
|
||||
void meta_wayland_init (void);
|
||||
void meta_wayland_finalize (void);
|
||||
|
||||
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
|
||||
* API after meta_wayland_init() has been called. */
|
||||
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
|
||||
|
||||
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
|
||||
|
||||
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
int vt,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_WAYLAND_PRIVATE_H */
|
||||
|
||||
@@ -276,42 +276,53 @@ static void
|
||||
handle_scroll_event (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
enum wl_pointer_axis axis;
|
||||
wl_fixed_t value;
|
||||
wl_fixed_t x_value = 0, y_value = 0;
|
||||
|
||||
notify_motion (seat, event);
|
||||
|
||||
if (!seat->pointer.focus_resource)
|
||||
return;
|
||||
|
||||
if (clutter_event_is_pointer_emulated (event))
|
||||
return;
|
||||
|
||||
switch (clutter_event_get_scroll_direction (event))
|
||||
{
|
||||
case CLUTTER_SCROLL_UP:
|
||||
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
|
||||
value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
y_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_DOWN:
|
||||
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
|
||||
value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
y_value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_LEFT:
|
||||
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
|
||||
value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
x_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_RIGHT:
|
||||
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
|
||||
value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
x_value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_SMOOTH:
|
||||
{
|
||||
double dx, dy;
|
||||
clutter_event_get_scroll_delta (event, &dx, &dy);
|
||||
x_value = wl_fixed_from_double (dx);
|
||||
y_value = wl_fixed_from_double (dy);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat->pointer.focus_resource)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource,
|
||||
clutter_event_get_time (event),
|
||||
axis,
|
||||
value);
|
||||
if (x_value)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
|
||||
WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
|
||||
if (y_value)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
|
||||
WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -43,12 +43,6 @@ struct _MetaWaylandDataSource
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
|
||||
void (*accept) (MetaWaylandDataSource * source,
|
||||
uint32_t serial, const char *mime_type);
|
||||
void (*send) (MetaWaylandDataSource * source,
|
||||
const char *mime_type, int32_t fd);
|
||||
void (*cancel) (MetaWaylandDataSource * source);
|
||||
};
|
||||
|
||||
struct _MetaWaylandSeat
|
||||
|
||||
@@ -82,7 +82,6 @@ surface_handle_buffer_destroy (struct wl_listener *listener, void *data)
|
||||
wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"Destroyed buffer while it was attached to the surface");
|
||||
surface->buffer = NULL;
|
||||
wl_list_remove (&surface->buffer_destroy_listener.link);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -262,9 +261,6 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
|
||||
CoglError *catch_error = NULL;
|
||||
CoglTexture *texture;
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
|
||||
buffer->resource,
|
||||
&catch_error));
|
||||
@@ -295,7 +291,7 @@ actor_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaSurfaceActor *surface_actor = surface->surface_actor;
|
||||
MetaWaylandBuffer *buffer = pending->buffer;
|
||||
|
||||
if (buffer_changed)
|
||||
if (buffer_changed && buffer)
|
||||
{
|
||||
ensure_buffer_texture (buffer);
|
||||
meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
|
||||
@@ -340,22 +336,6 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
|
||||
|
||||
if (pending->frame_extents_changed)
|
||||
meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
|
||||
|
||||
if (pending->maximized.changed)
|
||||
{
|
||||
if (pending->maximized.value)
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
}
|
||||
|
||||
if (pending->fullscreen.changed)
|
||||
{
|
||||
if (pending->fullscreen.value)
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
else
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -381,8 +361,6 @@ double_buffered_state_init (MetaWaylandDoubleBufferedState *state)
|
||||
wl_list_init (&state->frame_callback_list);
|
||||
|
||||
state->frame_extents_changed = FALSE;
|
||||
state->maximized.changed = FALSE;
|
||||
state->fullscreen.changed = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -650,18 +628,9 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
static void
|
||||
destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
|
||||
{
|
||||
wl_list_remove (&extension->surface_destroy_listener.link);
|
||||
extension->resource = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
extension_handle_surface_destroy (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *extension = wl_container_of (listener, extension, surface_destroy_listener);
|
||||
wl_resource_destroy (extension->resource);
|
||||
}
|
||||
|
||||
static int
|
||||
get_resource_version (struct wl_resource *master_resource,
|
||||
int max_version)
|
||||
@@ -671,23 +640,22 @@ get_resource_version (struct wl_resource *master_resource,
|
||||
|
||||
static gboolean
|
||||
create_surface_extension (MetaWaylandSurfaceExtension *extension,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *master_resource,
|
||||
struct wl_resource *surface_resource,
|
||||
guint32 id,
|
||||
int max_version,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation,
|
||||
wl_resource_destroy_func_t destructor)
|
||||
wl_resource_destroy_func_t destructor,
|
||||
MetaWaylandSurface *surface,
|
||||
struct wl_resource *master_resource,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_client *client;
|
||||
|
||||
if (extension->resource != NULL)
|
||||
return FALSE;
|
||||
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
extension->resource = wl_resource_create (client, interface, get_resource_version (master_resource, max_version), id);
|
||||
wl_resource_set_implementation (extension->resource, implementation, extension, destructor);
|
||||
|
||||
extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
|
||||
wl_resource_add_destroy_listener (surface_resource, &extension->surface_destroy_listener);
|
||||
wl_resource_set_implementation (extension->resource, implementation, surface, destructor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -714,11 +682,10 @@ xdg_shell_pong (struct wl_client *client,
|
||||
static void
|
||||
xdg_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (xdg_surface);
|
||||
destroy_surface_extension (&surface->xdg_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -733,8 +700,7 @@ xdg_surface_set_transient_for (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *parent_resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWindow *transient_for = NULL;
|
||||
|
||||
if (parent_resource)
|
||||
@@ -754,8 +720,7 @@ xdg_surface_set_margin (struct wl_client *client,
|
||||
int32_t top_margin,
|
||||
int32_t bottom_margin)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
surface->pending.frame_extents_changed = TRUE;
|
||||
surface->pending.frame_extents.left = left_margin;
|
||||
@@ -769,8 +734,7 @@ xdg_surface_set_title (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
}
|
||||
@@ -780,8 +744,7 @@ xdg_surface_set_app_id (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *app_id)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_set_wm_class (surface->window, app_id, app_id);
|
||||
}
|
||||
@@ -816,8 +779,7 @@ xdg_surface_move (struct wl_client *client,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
@@ -828,7 +790,7 @@ xdg_surface_move (struct wl_client *client,
|
||||
}
|
||||
|
||||
static MetaGrabOp
|
||||
grab_op_for_edge (int edge)
|
||||
grab_op_for_xdg_surface_resize_edge (int edge)
|
||||
{
|
||||
switch (edge)
|
||||
{
|
||||
@@ -862,15 +824,14 @@ xdg_surface_resize (struct wl_client *client,
|
||||
guint32 edges)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_xdg_surface_resize_edge (edges));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -882,55 +843,51 @@ xdg_surface_set_output (struct wl_client *client,
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
xdg_surface_request_change_state (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t state_type,
|
||||
uint32_t value,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
surface->pending.fullscreen.changed = TRUE;
|
||||
surface->pending.fullscreen.value = TRUE;
|
||||
surface->state_changed_serial = serial;
|
||||
|
||||
switch (state_type)
|
||||
{
|
||||
case XDG_SURFACE_STATE_MAXIMIZED:
|
||||
if (value)
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
break;
|
||||
case XDG_SURFACE_STATE_FULLSCREEN:
|
||||
if (value)
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
else
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_unset_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
xdg_surface_ack_change_state (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t state_type,
|
||||
uint32_t value,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.fullscreen.changed = TRUE;
|
||||
surface->pending.fullscreen.value = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.maximized.changed = TRUE;
|
||||
surface->pending.maximized.value = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_unset_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.maximized.changed = TRUE;
|
||||
surface->pending.maximized.value = FALSE;
|
||||
/* Do nothing for now. In the future, we'd imagine that
|
||||
* we'd ignore attaches when we have a state pending that
|
||||
* we haven't had the client ACK'd, to prevent a race
|
||||
* condition when we have an in-flight attach when the
|
||||
* client gets the new state. */
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_minimized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_minimize (surface->window);
|
||||
}
|
||||
@@ -944,10 +901,8 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
|
||||
xdg_surface_move,
|
||||
xdg_surface_resize,
|
||||
xdg_surface_set_output,
|
||||
xdg_surface_set_fullscreen,
|
||||
xdg_surface_unset_fullscreen,
|
||||
xdg_surface_set_maximized,
|
||||
xdg_surface_unset_maximized,
|
||||
xdg_surface_request_change_state,
|
||||
xdg_surface_ack_change_state,
|
||||
xdg_surface_set_minimized,
|
||||
};
|
||||
|
||||
@@ -959,11 +914,12 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_surface, client, surface_resource, resource, id,
|
||||
if (!create_surface_extension (&surface->xdg_surface,
|
||||
META_XDG_SURFACE_VERSION,
|
||||
&xdg_surface_interface,
|
||||
&meta_wayland_xdg_surface_interface,
|
||||
xdg_surface_destructor))
|
||||
xdg_surface_destructor,
|
||||
surface, resource, id))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -978,11 +934,10 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
static void
|
||||
xdg_popup_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (xdg_popup);
|
||||
destroy_surface_extension (&surface->xdg_popup);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1015,11 +970,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||
return;
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id,
|
||||
if (!create_surface_extension (&surface->xdg_popup,
|
||||
META_XDG_POPUP_VERSION,
|
||||
&xdg_popup_interface,
|
||||
&meta_wayland_xdg_popup_interface,
|
||||
xdg_popup_destructor))
|
||||
xdg_popup_destructor,
|
||||
surface, resource, id))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1035,8 +991,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
surface->window->placed = TRUE;
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
|
||||
surface->window->type = META_WINDOW_DROPDOWN_MENU;
|
||||
meta_window_type_changed (surface->window);
|
||||
meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
|
||||
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
}
|
||||
@@ -1102,13 +1057,264 @@ bind_xdg_shell (struct wl_client *client,
|
||||
wl_client_add_destroy_listener (client, &xdg_shell->client_destroy_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (&surface->wl_shell_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_pong (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
meta_display_pong_for_serial (display, serial);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_move (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING);
|
||||
}
|
||||
|
||||
static MetaGrabOp
|
||||
grab_op_for_wl_shell_surface_resize_edge (int edge)
|
||||
{
|
||||
switch (edge)
|
||||
{
|
||||
case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
|
||||
return META_GRAB_OP_RESIZING_NW;
|
||||
case WL_SHELL_SURFACE_RESIZE_TOP:
|
||||
return META_GRAB_OP_RESIZING_N;
|
||||
case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
|
||||
return META_GRAB_OP_RESIZING_NE;
|
||||
case WL_SHELL_SURFACE_RESIZE_RIGHT:
|
||||
return META_GRAB_OP_RESIZING_E;
|
||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
|
||||
return META_GRAB_OP_RESIZING_SE;
|
||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM:
|
||||
return META_GRAB_OP_RESIZING_S;
|
||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
|
||||
return META_GRAB_OP_RESIZING_SW;
|
||||
case WL_SHELL_SURFACE_RESIZE_LEFT:
|
||||
return META_GRAB_OP_RESIZING_W;
|
||||
default:
|
||||
g_warning ("invalid edge: %d", edge);
|
||||
return META_GRAB_OP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_resize (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial,
|
||||
uint32_t edges)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_wl_shell_surface_resize_edge (edges));
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
SURFACE_STATE_TOPLEVEL,
|
||||
SURFACE_STATE_FULLSCREEN,
|
||||
SURFACE_STATE_MAXIMIZED,
|
||||
} SurfaceState;
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_state (MetaWaylandSurface *surface,
|
||||
SurfaceState state)
|
||||
{
|
||||
if (state == SURFACE_STATE_FULLSCREEN)
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
else
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
|
||||
if (state == SURFACE_STATE_MAXIMIZED)
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
|
||||
else
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_toplevel (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_transient (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *parent_resource,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
uint32_t flags)
|
||||
{
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
|
||||
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
meta_window_move (surface->window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
surface->window->placed = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t method,
|
||||
uint32_t framerate,
|
||||
struct wl_resource *output)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_FULLSCREEN);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_popup (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial,
|
||||
struct wl_resource *parent_resource,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
uint32_t flags)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
|
||||
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
meta_window_move (surface->window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
surface->window->placed = TRUE;
|
||||
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *output)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_MAXIMIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_title (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_class (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *class_)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_set_wm_class (surface->window, class_, class_);
|
||||
}
|
||||
|
||||
static const struct wl_shell_surface_interface meta_wayland_wl_shell_surface_interface = {
|
||||
wl_shell_surface_pong,
|
||||
wl_shell_surface_move,
|
||||
wl_shell_surface_resize,
|
||||
wl_shell_surface_set_toplevel,
|
||||
wl_shell_surface_set_transient,
|
||||
wl_shell_surface_set_fullscreen,
|
||||
wl_shell_surface_set_popup,
|
||||
wl_shell_surface_set_maximized,
|
||||
wl_shell_surface_set_title,
|
||||
wl_shell_surface_set_class,
|
||||
};
|
||||
|
||||
static void
|
||||
wl_shell_get_shell_surface (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t id,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->wl_shell_surface,
|
||||
META_WL_SHELL_SURFACE_VERSION,
|
||||
&wl_shell_surface_interface,
|
||||
&meta_wayland_wl_shell_surface_interface,
|
||||
wl_shell_surface_destructor,
|
||||
surface, resource, id))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"wl_shell::get_shell_surface already requested");
|
||||
return;
|
||||
}
|
||||
|
||||
meta_wayland_surface_make_toplevel (surface);
|
||||
surface->window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
}
|
||||
|
||||
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
|
||||
wl_shell_get_shell_surface,
|
||||
};
|
||||
|
||||
static void
|
||||
bind_wl_shell (struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &wl_shell_interface,
|
||||
MIN (META_WL_SHELL_VERSION, version), id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_wl_shell_interface, data, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (gtk_surface);
|
||||
destroy_surface_extension (&surface->gtk_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1121,8 +1327,7 @@ set_dbus_properties (struct wl_client *client,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
/* Broken client, let it die instead of us */
|
||||
if (!surface->window)
|
||||
@@ -1152,11 +1357,12 @@ get_gtk_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->gtk_surface, client, surface_resource, resource, id,
|
||||
if (!create_surface_extension (&surface->gtk_surface,
|
||||
META_GTK_SURFACE_VERSION,
|
||||
>k_surface_interface,
|
||||
&meta_wayland_gtk_surface_interface,
|
||||
gtk_surface_destructor))
|
||||
gtk_surface_destructor,
|
||||
surface, resource, id))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1238,8 +1444,6 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface)
|
||||
|
||||
if (surface->sub.synchronous)
|
||||
commit_double_buffered_state (surface, pending_surface_state);
|
||||
|
||||
double_buffered_state_reset (pending_surface_state);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1253,8 +1457,7 @@ unparent_actor (MetaWaylandSurface *surface)
|
||||
static void
|
||||
wl_subsurface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (surface->sub.parent)
|
||||
{
|
||||
@@ -1266,7 +1469,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
double_buffered_state_destroy (&surface->sub.pending_surface_state);
|
||||
destroy_surface_extension (subsurface);
|
||||
destroy_surface_extension (&surface->subsurface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1282,8 +1485,7 @@ wl_subsurface_set_position (struct wl_client *client,
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
surface->sub.pending_x = x;
|
||||
surface->sub.pending_y = y;
|
||||
@@ -1333,8 +1535,7 @@ wl_subsurface_place_above (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *sibling_resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
|
||||
|
||||
if (!is_valid_sibling (surface, sibling))
|
||||
@@ -1356,8 +1557,7 @@ wl_subsurface_place_below (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *sibling_resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
|
||||
|
||||
if (!is_valid_sibling (surface, sibling))
|
||||
@@ -1378,10 +1578,7 @@ static void
|
||||
wl_subsurface_set_sync (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *subsurface =
|
||||
wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
surface->sub.synchronous = TRUE;
|
||||
}
|
||||
@@ -1390,10 +1587,7 @@ static void
|
||||
wl_subsurface_set_desync (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *subsurface =
|
||||
wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (surface->sub.synchronous)
|
||||
subsurface_parent_surface_committed (surface);
|
||||
@@ -1439,11 +1633,12 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id,
|
||||
if (!create_surface_extension (&surface->subsurface,
|
||||
META_GTK_SURFACE_VERSION,
|
||||
&wl_subsurface_interface,
|
||||
&meta_wayland_subsurface_interface,
|
||||
wl_subsurface_destructor))
|
||||
wl_subsurface_destructor,
|
||||
surface, resource, id))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1489,6 +1684,11 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor)
|
||||
compositor, bind_xdg_shell) == NULL)
|
||||
g_error ("Failed to register a global xdg-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
&wl_shell_interface, 1,
|
||||
compositor, bind_wl_shell) == NULL)
|
||||
g_error ("Failed to register a global wl-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
>k_shell_interface,
|
||||
META_GTK_SHELL_VERSION,
|
||||
@@ -1510,6 +1710,58 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
if (surface->xdg_surface.resource)
|
||||
xdg_surface_send_configure (surface->xdg_surface.resource,
|
||||
new_width, new_height);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
|
||||
0, new_width, new_height);
|
||||
}
|
||||
|
||||
static void
|
||||
send_change_state (MetaWaylandSurface *surface,
|
||||
uint32_t state_type,
|
||||
uint32_t value)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
{
|
||||
uint32_t serial;
|
||||
|
||||
if (surface->state_changed_serial != 0)
|
||||
{
|
||||
serial = surface->state_changed_serial;
|
||||
surface->state_changed_serial = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
}
|
||||
|
||||
xdg_surface_send_change_state (surface->xdg_surface.resource, state_type, value, serial);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_maximized (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1530,16 +1782,23 @@ void
|
||||
meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
guint32 serial)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
|
||||
|
||||
if (xdg_shell == NULL)
|
||||
if (surface->xdg_surface.resource)
|
||||
{
|
||||
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
|
||||
return;
|
||||
}
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
|
||||
|
||||
xdg_shell_send_ping (xdg_shell, serial);
|
||||
if (xdg_shell == NULL)
|
||||
{
|
||||
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
|
||||
return;
|
||||
}
|
||||
|
||||
xdg_shell_send_ping (xdg_shell, serial);
|
||||
}
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
{
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1548,3 +1807,16 @@ meta_wayland_surface_delete (MetaWaylandSurface *surface)
|
||||
if (surface->xdg_surface.resource)
|
||||
xdg_surface_send_delete (surface->xdg_surface.resource);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
if (surface->xdg_popup.resource)
|
||||
xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
|
||||
}
|
||||
|
||||
@@ -41,12 +41,6 @@ struct _MetaWaylandBuffer
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint changed : 1;
|
||||
guint value : 1;
|
||||
} MetaWaylandStateFlag;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* wl_surface.attach */
|
||||
@@ -67,15 +61,11 @@ typedef struct
|
||||
|
||||
gboolean frame_extents_changed;
|
||||
GtkBorder frame_extents;
|
||||
|
||||
MetaWaylandStateFlag fullscreen;
|
||||
MetaWaylandStateFlag maximized;
|
||||
} MetaWaylandDoubleBufferedState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
} MetaWaylandSurfaceExtension;
|
||||
|
||||
struct _MetaWaylandSurface
|
||||
@@ -86,6 +76,7 @@ struct _MetaWaylandSurface
|
||||
MetaWindow *window;
|
||||
MetaWaylandSurfaceExtension xdg_surface;
|
||||
MetaWaylandSurfaceExtension xdg_popup;
|
||||
MetaWaylandSurfaceExtension wl_shell_surface;
|
||||
MetaWaylandSurfaceExtension gtk_surface;
|
||||
MetaWaylandSurfaceExtension subsurface;
|
||||
|
||||
@@ -107,6 +98,8 @@ struct _MetaWaylandSurface
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
uint32_t state_changed_serial;
|
||||
|
||||
/* All the pending state, that wl_surface.commit will apply. */
|
||||
MetaWaylandDoubleBufferedState pending;
|
||||
};
|
||||
@@ -124,6 +117,10 @@ void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *s
|
||||
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
int width,
|
||||
int height);
|
||||
void meta_wayland_surface_send_maximized (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_activated (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_deactivated (MetaWaylandSurface *surface);
|
||||
@@ -132,4 +129,7 @@ void meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
guint32 serial);
|
||||
void meta_wayland_surface_delete (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||
#define META_WL_COMPOSITOR_VERSION 3
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
|
||||
#define META_WL_SHELL_VERSION 1
|
||||
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
|
||||
#define META_WL_OUTPUT_VERSION 2
|
||||
#define META_XSERVER_VERSION 1
|
||||
@@ -52,9 +53,10 @@
|
||||
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
|
||||
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
|
||||
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
|
||||
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
|
||||
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
|
||||
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */
|
||||
#define META_WL_SHELL_SURFACE_VERSION 1 /* from wl_shell */
|
||||
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
|
||||
#define META_WL_SUBSURFACE_VERSION 1 /* from wl_subcompositor */
|
||||
|
||||
/* The first version to implement a specific event */
|
||||
|
||||
@@ -643,6 +643,8 @@ meta_wayland_init (void)
|
||||
|
||||
clutter_wayland_set_compositor_display (compositor->wayland_display);
|
||||
|
||||
/* If we're running on bare metal, we're a display server,
|
||||
* so start talking to weston-launch. */
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
compositor->launcher = meta_launcher_new ();
|
||||
@@ -728,7 +730,22 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring VT switch keybinding, not running as VT manager");
|
||||
g_debug ("Ignoring VT switch keybinding, not running as display server");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
|
||||
GError **error)
|
||||
{
|
||||
if (compositor->launcher)
|
||||
{
|
||||
return meta_launcher_activate_vt (compositor->launcher, -1, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring activate_session, not running as display server");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
53
src/wayland/meta-wayland.h
Normal file
53
src/wayland/meta-wayland.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_H
|
||||
#define META_WAYLAND_H
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
void meta_wayland_init (void);
|
||||
void meta_wayland_finalize (void);
|
||||
|
||||
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
|
||||
* API after meta_wayland_init() has been called. */
|
||||
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
|
||||
|
||||
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
int vt,
|
||||
GError **error);
|
||||
gboolean meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
|
||||
GError **error);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-weston-launch.h"
|
||||
|
||||
struct _MetaLauncher
|
||||
@@ -179,11 +181,11 @@ meta_launcher_set_drm_fd (MetaLauncher *self,
|
||||
return ok;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
meta_launcher_open_input_device (MetaLauncher *self,
|
||||
const char *name,
|
||||
int flags,
|
||||
GError **error)
|
||||
const char *name,
|
||||
int flags,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_open *message;
|
||||
GSocketControlMessage *cmsg;
|
||||
@@ -232,6 +234,17 @@ meta_launcher_enter (MetaLauncher *launcher)
|
||||
cogl_kms_display_queue_modes_reset (cogl_display);
|
||||
|
||||
clutter_evdev_reclaim_devices ();
|
||||
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
/* When we mode-switch back, we need to immediately queue a redraw
|
||||
* in case nothing else queued one for us, and force the cursor to
|
||||
* update. */
|
||||
|
||||
clutter_actor_queue_redraw (compositor->stage);
|
||||
meta_cursor_tracker_force_update (compositor->seat->cursor_tracker);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -251,6 +264,13 @@ on_evdev_device_open (const char *path,
|
||||
return meta_launcher_open_input_device (launcher, path, flags, error);
|
||||
}
|
||||
|
||||
static void
|
||||
on_evdev_device_close (int fd,
|
||||
gpointer user_data)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_vt_enter (MetaLauncher *launcher)
|
||||
{
|
||||
@@ -354,8 +374,6 @@ meta_launcher_new (void)
|
||||
|
||||
self->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
|
||||
|
||||
clutter_evdev_set_open_callback (on_evdev_device_open, self);
|
||||
|
||||
self->nested_context = g_main_context_new ();
|
||||
self->nested_loop = g_main_loop_new (self->nested_context, FALSE);
|
||||
|
||||
@@ -369,6 +387,10 @@ meta_launcher_new (void)
|
||||
g_source_attach (self->inner_source, self->nested_context);
|
||||
g_source_unref (self->inner_source);
|
||||
|
||||
clutter_evdev_set_device_callbacks (on_evdev_device_open,
|
||||
on_evdev_device_close,
|
||||
self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -388,7 +410,7 @@ meta_launcher_free (MetaLauncher *launcher)
|
||||
|
||||
gboolean
|
||||
meta_launcher_activate_vt (MetaLauncher *launcher,
|
||||
int vt,
|
||||
signed char vt,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_activate_vt message;
|
||||
|
||||
@@ -29,18 +29,10 @@ MetaLauncher *meta_launcher_new (void);
|
||||
void meta_launcher_free (MetaLauncher *self);
|
||||
|
||||
gboolean meta_launcher_activate_vt (MetaLauncher *self,
|
||||
int number,
|
||||
signed char vt,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_launcher_set_drm_fd (MetaLauncher *self,
|
||||
int drm_fd,
|
||||
GError **error);
|
||||
gboolean meta_launcher_set_master (MetaLauncher *self,
|
||||
gboolean master,
|
||||
GError **error);
|
||||
int meta_launcher_open_input_device (MetaLauncher *self,
|
||||
const char *name,
|
||||
int flags,
|
||||
GError **error);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,10 +47,19 @@ xserver_set_window_id (struct wl_client *client,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
/* If the window has an existing surface, like if we're
|
||||
* undecorating or decorating the window, then we need
|
||||
* to detach the window from its old surface.
|
||||
*/
|
||||
if (window->surface)
|
||||
window->surface->window = NULL;
|
||||
|
||||
meta_wayland_surface_make_toplevel (surface);
|
||||
|
||||
surface->window = window;
|
||||
window->surface = surface;
|
||||
|
||||
meta_compositor_window_surface_changed (display->compositor, window);
|
||||
}
|
||||
|
||||
static const struct xserver_interface xserver_implementation = {
|
||||
|
||||
@@ -80,6 +80,7 @@ struct weston_launch {
|
||||
struct termios terminal_attributes;
|
||||
int kb_mode;
|
||||
enum vt_state vt_state;
|
||||
unsigned vt;
|
||||
|
||||
int drm_fd;
|
||||
};
|
||||
@@ -274,6 +275,7 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
struct weston_launcher_activate_vt *message;
|
||||
unsigned vt;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
|
||||
reply.ret = -1;
|
||||
@@ -285,7 +287,13 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
|
||||
message = msg->msg_iov->iov_base;
|
||||
|
||||
reply.ret = ioctl(wl->tty, VT_ACTIVATE, message->vt);
|
||||
/* Negative values mean that we're activating our own VT */
|
||||
if (message->vt > 0)
|
||||
vt = message->vt;
|
||||
else
|
||||
vt = wl->vt;
|
||||
|
||||
reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt);
|
||||
if (reply.ret < 0)
|
||||
reply.ret = -errno;
|
||||
|
||||
@@ -331,6 +339,13 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (major(s.st_rdev) != INPUT_MAJOR) {
|
||||
fprintf(stderr, "Device %s is not an input device\n",
|
||||
message->path);
|
||||
reply.ret = -EPERM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
fd = open(message->path, message->flags);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error opening device %s: %m\n",
|
||||
@@ -339,15 +354,6 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (major(s.st_rdev) != INPUT_MAJOR) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
fprintf(stderr, "Device %s is not an input device\n",
|
||||
message->path);
|
||||
reply.ret = -EPERM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
err0:
|
||||
memset(&nmsg, 0, sizeof nmsg);
|
||||
nmsg.msg_iov = &iov;
|
||||
@@ -554,7 +560,7 @@ setup_tty(struct weston_launch *wl)
|
||||
struct stat buf;
|
||||
struct termios raw_attributes;
|
||||
struct vt_mode mode = { 0 };
|
||||
char *session, *tty;
|
||||
char *session;
|
||||
char path[PATH_MAX];
|
||||
int ok;
|
||||
|
||||
@@ -562,44 +568,13 @@ setup_tty(struct weston_launch *wl)
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current session");
|
||||
|
||||
ok = sd_session_get_tty(session, &tty);
|
||||
if (ok == 0) {
|
||||
/* Old systemd only has the tty name in the TTY
|
||||
field, new one has the full char device path.
|
||||
|
||||
Check what we have and fix it properly.
|
||||
*/
|
||||
if (strncmp(tty, "/dev", strlen("/dev")) == 0) {
|
||||
strncpy(path, tty, PATH_MAX);
|
||||
path[PATH_MAX-1] = 0;
|
||||
} else {
|
||||
snprintf(path, PATH_MAX, "/dev/%s", tty);
|
||||
}
|
||||
|
||||
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
free(tty);
|
||||
#ifdef HAVE_SD_SESSION_GET_VT
|
||||
} else if (ok == -ENOENT) {
|
||||
unsigned vt;
|
||||
|
||||
/* Negative errnos are cool, right?
|
||||
So cool that we can't distinguish "session not found"
|
||||
from "key does not exist in the session file"!
|
||||
Let's assume the latter, as we got the value
|
||||
from sd_pid_get_session()...
|
||||
*/
|
||||
|
||||
ok = sd_session_get_vt(session, &vt);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current TTY");
|
||||
|
||||
snprintf(path, PATH_MAX, "/dev/tty%u", vt);
|
||||
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
free(tty);
|
||||
#endif
|
||||
} else
|
||||
ok = sd_session_get_vt(session, &wl->vt);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current TTY");
|
||||
|
||||
snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
|
||||
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
|
||||
if (wl->tty < 0)
|
||||
error(1, errno, "failed to open tty");
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ struct weston_launcher_open {
|
||||
|
||||
struct weston_launcher_activate_vt {
|
||||
struct weston_launcher_message header;
|
||||
int vt;
|
||||
signed char vt;
|
||||
};
|
||||
|
||||
struct weston_launcher_reply {
|
||||
|
||||
Reference in New Issue
Block a user