Compare commits
3 Commits
wip/icons
...
wip/surfac
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2210c30cba | ||
![]() |
6b98ac3d1f | ||
![]() |
13ddd366a9 |
25
NEWS
25
NEWS
@@ -1,28 +1,3 @@
|
||||
3.11.91
|
||||
=======
|
||||
* Don't use keysym to match keybindings [Rui; #678001]
|
||||
* Fix message tray icons showing up blank (again) [Adel; #725180]
|
||||
* Improve keybinding lookups [Rui; #725588]
|
||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
|
||||
* Fix positioning of manually positioned windows [Owen; #724049]
|
||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
|
||||
#724969, #725216, #724402, #722266, #725338, #725525]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.90
|
||||
=======
|
||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
||||
* Make tile previews a compositor effect [Stefano, Florian; #665758]
|
||||
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257,
|
||||
#724258, #720631, #724364, #724472]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah,
|
||||
Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
3.11.5
|
||||
======
|
||||
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
|
||||
|
@@ -5,7 +5,7 @@ srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="mutter"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
REQUIRED_AUTOMAKE_VERSION=1.13
|
||||
|
||||
(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], [91])
|
||||
m4_define([mutter_micro_version], [5])
|
||||
|
||||
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.5
|
||||
$CLUTTER_PACKAGE >= 1.17.1
|
||||
cogl-1.0 >= 1.17.1
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
@@ -142,6 +142,11 @@ 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,22 +40,19 @@
|
||||
|
||||
<enum name="version">
|
||||
<description summary="latest protocol version">
|
||||
The 'current' member of this enum gives the version of the
|
||||
protocol. Implementations can compare this to the version
|
||||
they implement using static_assert to ensure the protocol and
|
||||
implementation versions match.
|
||||
Use this enum to check the protocol version, and it will be updated
|
||||
automatically.
|
||||
</description>
|
||||
<entry name="current" value="3" summary="Always the latest version"/>
|
||||
<entry name="current" value="2" summary="Always the latest version"/>
|
||||
</enum>
|
||||
|
||||
|
||||
<request name="use_unstable_version">
|
||||
<description summary="enable use of this unstable version">
|
||||
Negotiate the unstable version of the interface. This
|
||||
mechanism is in place to ensure client and server agree on the
|
||||
unstable versions of the protocol that they speak or exit
|
||||
cleanly if they don't agree. This request will go away once
|
||||
the xdg-shell protocol is stable.
|
||||
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.
|
||||
</description>
|
||||
<arg name="version" type="int"/>
|
||||
</request>
|
||||
@@ -278,87 +275,113 @@
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<enum name="state">
|
||||
<description summary="types of state on the surface">
|
||||
The different state values used on the surface. This is designed for
|
||||
state values like maximized, fullscreen. It is paired with the
|
||||
request_change_state event to ensure that both the client and the
|
||||
compositor setting the state can be synchronized.
|
||||
|
||||
States set in this way are double-buffered. They will get applied on
|
||||
the next commit.
|
||||
|
||||
Desktop environments may extend this enum by taking up a range of
|
||||
values and documenting the range they chose in this description.
|
||||
They are not required to document the values for the range that they
|
||||
chose. Ideally, any good extensions from a desktop environment should
|
||||
make its way into standardization into this enum.
|
||||
|
||||
The current reserved ranges are:
|
||||
|
||||
0x0000 - 0x0FFF: xdg-shell core values, documented below.
|
||||
0x1000 - 0x1FFF: GNOME
|
||||
<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.
|
||||
</description>
|
||||
<entry name="maximized" value="1" summary="the surface is maximized">
|
||||
A non-zero value indicates the surface is maximized. Otherwise,
|
||||
the surface is unmaximized.
|
||||
</entry>
|
||||
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
|
||||
A non-zero value indicates the surface is fullscreen. Otherwise,
|
||||
the surface is not fullscreen.
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<request name="request_change_state">
|
||||
<description summary="client requests to change a surface's state">
|
||||
This asks the compositor to change the state. If the compositor wants
|
||||
to change the state, it will send a change_state event with the same
|
||||
state_type, value, and serial, and the event flow continues as if it
|
||||
it was initiated by the compositor.
|
||||
|
||||
If the compositor does not want to change the state, it will send a
|
||||
change_state to the client with the old value of the state.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="an event serial">
|
||||
This serial is so the client can know which change_state event corresponds
|
||||
to which request_change_state request it sent out.
|
||||
</arg>
|
||||
</request>
|
||||
|
||||
<event name="change_state">
|
||||
<description summary="compositor wants to change a surface's state">
|
||||
This event tells the client to change a surface's state. The client
|
||||
should respond with an ack_change_state request to the compositor to
|
||||
guarantee that the compositor knows that the client has seen it.
|
||||
</description>
|
||||
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
|
||||
</event>
|
||||
|
||||
<request name="ack_change_state">
|
||||
<description summary="ack a change_state event">
|
||||
When a change_state event is received, a client should then ack it
|
||||
using the ack_change_state request to ensure that the compositor
|
||||
knows the client has seen the event.
|
||||
|
||||
By this point, the state is confirmed, and the next attach should
|
||||
contain the buffer drawn for the new state value.
|
||||
|
||||
The values here need to be the same as the values in the cooresponding
|
||||
change_state event.
|
||||
<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.
|
||||
</description>
|
||||
</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.
|
||||
</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>
|
||||
</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.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="a serial to pass to change_state"/>
|
||||
</request>
|
||||
|
||||
<request name="set_minimized">
|
||||
<description summary="minimize the surface">
|
||||
Minimize the surface.
|
||||
<description summary="set the surface state as minimized">
|
||||
Set the surface minimized state.
|
||||
|
||||
Setting one state won't unset another state.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
|
@@ -29,18 +29,6 @@
|
||||
<KeyListEntry name="move-to-workspace-down"
|
||||
_description="Move window one workspace down" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-left"
|
||||
_description="Move window one monitor to the left" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-right"
|
||||
_description="Move window one monitor to the right" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-up"
|
||||
_description="Move window one monitor up" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-down"
|
||||
_description="Move window one monitor down" />
|
||||
|
||||
<KeyListEntry name="switch-applications"
|
||||
_description="Switch applications"/>
|
||||
|
||||
|
@@ -6,7 +6,6 @@ lib_LTLIBRARIES = libmutter-wayland.la
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
@@ -113,6 +112,8 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/display.c \
|
||||
core/display-private.h \
|
||||
meta/display.h \
|
||||
ui/draw-workspace.c \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/edid-parse.c \
|
||||
@@ -128,8 +129,8 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/group-props.h \
|
||||
core/group.c \
|
||||
meta/group.h \
|
||||
core/icons.c \
|
||||
core/icons.h \
|
||||
core/iconcache.c \
|
||||
core/iconcache.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -183,13 +184,16 @@ libmutter_wayland_la_SOURCES = \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
ui/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
ui/tabpopup.h \
|
||||
ui/tile-preview.c \
|
||||
ui/tile-preview.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme.c \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
|
@@ -76,7 +76,6 @@
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "util-private.h"
|
||||
#include "frame.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
@@ -141,19 +140,6 @@ meta_compositor_destroy (MetaCompositor *compositor)
|
||||
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
|
||||
}
|
||||
|
||||
static void
|
||||
add_win (MetaWindow *window)
|
||||
{
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
meta_window_actor_new (window);
|
||||
|
||||
sync_actor_stacking (info);
|
||||
}
|
||||
|
||||
static void
|
||||
process_damage (MetaCompositor *compositor,
|
||||
XDamageNotifyEvent *event,
|
||||
@@ -330,36 +316,39 @@ meta_focus_stage_window (MetaScreen *screen,
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (window == None)
|
||||
return;
|
||||
if (window == None)
|
||||
return;
|
||||
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
window,
|
||||
timestamp);
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
META_FOCUS_STAGE,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
META_FOCUS_STAGE,
|
||||
None,
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_stage_is_focused (MetaScreen *screen)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
Window window;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return TRUE;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return FALSE;
|
||||
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (window == None)
|
||||
return FALSE;
|
||||
|
||||
return (screen->display->focus_xwindow == window);
|
||||
return (screen->display->focus_type == META_FOCUS_STAGE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -436,6 +425,45 @@ begin_modal_x11 (MetaScreen *screen,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
begin_modal_wayland (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
|
||||
goto fail;
|
||||
|
||||
pointer_grabbed = TRUE;
|
||||
}
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard,
|
||||
timestamp))
|
||||
goto fail;
|
||||
|
||||
keyboard_grabbed = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
if (pointer_grabbed)
|
||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
||||
if (keyboard_grabbed)
|
||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard, timestamp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
@@ -454,7 +482,7 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
return FALSE;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
ok = TRUE;
|
||||
ok = begin_modal_wayland (screen, plugin, options, timestamp);
|
||||
else
|
||||
ok = begin_modal_x11 (screen, plugin, options, timestamp);
|
||||
if (!ok)
|
||||
@@ -482,7 +510,15 @@ meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
|
||||
g_return_if_fail (compositor->modal_plugin == plugin);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
@@ -786,13 +822,20 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
{
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
/* Window was already added previously, probably coming
|
||||
* back from hiding */
|
||||
if (window->compositor_private != NULL)
|
||||
return;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_add_window\n");
|
||||
meta_error_trap_push (display);
|
||||
|
||||
add_win (window);
|
||||
|
||||
meta_window_actor_new (window);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
sync_actor_stacking (info);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -894,66 +937,6 @@ 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
|
||||
@@ -965,7 +948,6 @@ event_is_passive_button_grab (MetaDisplay *display,
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (info->screen);
|
||||
@@ -974,30 +956,24 @@ 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;
|
||||
@@ -1017,12 +993,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaScreen *screen = display->screens->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
|
||||
{
|
||||
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
|
||||
@@ -1032,13 +1002,43 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
maybe_spoof_event_as_stage_event (info, window, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
if (window)
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
l = meta_display_get_screens (compositor->display);
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaScreen *screen = l->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
maybe_spoof_event_as_stage_event (info, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
@@ -1695,31 +1695,3 @@ meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
||||
else
|
||||
return monotonic_time + compositor->server_time_offset;
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (!info->plugin_mgr)
|
||||
return;
|
||||
|
||||
meta_plugin_manager_show_tile_preview (info->plugin_mgr,
|
||||
window, tile_rect, tile_monitor_number);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_hide_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (!info->plugin_mgr)
|
||||
return;
|
||||
|
||||
meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
|
||||
}
|
||||
|
@@ -324,44 +324,3 @@ meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
|
||||
else
|
||||
return meta_plugin_complete_display_change (plugin, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
if (klass->show_tile_preview)
|
||||
{
|
||||
klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
if (klass->hide_tile_preview)
|
||||
{
|
||||
klass->hide_tile_preview (plugin);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@@ -75,9 +75,4 @@ gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
|
||||
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
|
||||
|
||||
gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
|
||||
#endif
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/screen.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#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>
|
||||
@@ -577,18 +576,8 @@ static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
|
||||
|
||||
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;
|
||||
return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
@@ -98,14 +97,6 @@ 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)
|
||||
{
|
||||
@@ -119,8 +110,6 @@ 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.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@@ -387,14 +387,6 @@ 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)
|
||||
{
|
||||
@@ -411,8 +403,6 @@ 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
|
||||
@@ -424,49 +414,26 @@ meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
|
||||
priv->last_height = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
Display *xdisplay = meta_display_get_xdisplay (priv->display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
}
|
||||
|
||||
static void
|
||||
window_decorated_notify (MetaWindow *window,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
|
||||
|
||||
free_damage (self);
|
||||
create_damage (self);
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_x11_new (MetaWindow *window)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = meta_window_get_display (window);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (window);
|
||||
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
|
||||
priv->window = window;
|
||||
priv->display = display;
|
||||
|
||||
create_damage (self);
|
||||
g_signal_connect_object (priv->window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
update_is_argb32 (self);
|
||||
|
||||
priv->unredirected = FALSE;
|
||||
sync_unredirected (self);
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#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"
|
||||
|
||||
@@ -25,8 +26,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);
|
||||
@@ -34,14 +35,6 @@ static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
enum {
|
||||
REPAINT_SCHEDULED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
@@ -121,13 +114,6 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
|
||||
signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
|
||||
}
|
||||
|
||||
@@ -178,14 +164,12 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
|
||||
return self->priv->texture;
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (meta_shaped_texture_update_area (priv->texture, x, y, width, height))
|
||||
g_signal_emit (self, signals[REPAINT_SCHEDULED], 0);
|
||||
return meta_shaped_texture_update_area (priv->texture, x, y, width, height);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -222,7 +206,7 @@ static gboolean
|
||||
is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return priv->frozen;
|
||||
return (priv->freeze_count > 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -273,19 +257,31 @@ meta_surface_actor_is_visible (MetaSurfaceActor *self)
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
||||
gboolean frozen)
|
||||
meta_surface_actor_freeze (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
priv->frozen = frozen;
|
||||
priv->freeze_count ++;
|
||||
}
|
||||
|
||||
if (!frozen && priv->needs_damage_all)
|
||||
void
|
||||
meta_surface_actor_thaw (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
/* 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. */
|
||||
g_critical ("Error in freeze/thaw accounting.");
|
||||
return;
|
||||
}
|
||||
|
||||
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)));
|
||||
@@ -293,6 +289,12 @@ meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
return is_frozen (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
|
||||
{
|
||||
@@ -311,9 +313,3 @@ 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,7 +6,6 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -36,8 +35,6 @@ struct _MetaSurfaceActorClass
|
||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||
|
||||
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActor
|
||||
@@ -53,7 +50,6 @@ 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,
|
||||
@@ -64,8 +60,8 @@ void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
gboolean meta_surface_actor_update_area (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
@@ -73,8 +69,9 @@ void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
|
||||
|
||||
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
|
||||
gboolean frozen);
|
||||
void meta_surface_actor_freeze (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_thaw (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
|
||||
|
||||
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
|
||||
|
@@ -5,6 +5,9 @@
|
||||
|
||||
#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"
|
||||
@@ -60,6 +63,5 @@ 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"
|
||||
@@ -68,9 +68,6 @@ struct _MetaWindowActorPrivate
|
||||
guint send_frame_messages_timer;
|
||||
gint64 frame_drawn_time;
|
||||
|
||||
guint repaint_scheduled_id;
|
||||
guint allocation_changed_id;
|
||||
|
||||
/*
|
||||
* These need to be counters rather than flags, since more plugins
|
||||
* can implement same effect; the practicality of stacking effects
|
||||
@@ -84,10 +81,10 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
/* List of FrameData for recent frames */
|
||||
GList *frames;
|
||||
guint freeze_count;
|
||||
|
||||
guint visible : 1;
|
||||
guint disposed : 1;
|
||||
guint redecorating : 1;
|
||||
|
||||
/* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN
|
||||
* client message using the most recent frame in ->frames */
|
||||
@@ -222,6 +219,26 @@ meta_window_actor_init (MetaWindowActor *self)
|
||||
priv->shadow_class = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
window_decorated_notify (MetaWindow *mw,
|
||||
GParamSpec *arg1,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (data);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
/*
|
||||
* Basically, we have to reconstruct the the internals of this object
|
||||
* from scratch, as everything has changed.
|
||||
*/
|
||||
priv->redecorating = TRUE;
|
||||
|
||||
/*
|
||||
* Recreate the contents.
|
||||
*/
|
||||
meta_window_actor_constructed (G_OBJECT (self));
|
||||
}
|
||||
|
||||
static void
|
||||
window_appears_focused_notify (MetaWindow *mw,
|
||||
GParamSpec *arg1,
|
||||
@@ -240,29 +257,11 @@ surface_allocation_changed_notify (ClutterActor *actor,
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_repaint_scheduled (MetaSurfaceActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (user_data);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
priv->repaint_scheduled = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_argb32 (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
/* 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;
|
||||
return meta_surface_actor_is_argb32 (priv->surface);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -278,19 +277,14 @@ static gboolean
|
||||
is_frozen (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
return priv->surface == NULL || priv->freeze_count > 0;
|
||||
return meta_surface_actor_is_frozen (priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_freeze (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->freeze_count == 0 && priv->surface)
|
||||
meta_surface_actor_set_frozen (priv->surface, TRUE);
|
||||
|
||||
priv->freeze_count ++;
|
||||
meta_surface_actor_freeze (priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -298,16 +292,11 @@ meta_window_actor_thaw (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->freeze_count <= 0)
|
||||
g_error ("Error in freeze/thaw accounting");
|
||||
meta_surface_actor_thaw (priv->surface);
|
||||
|
||||
priv->freeze_count--;
|
||||
if (priv->freeze_count > 0)
|
||||
if (is_frozen (self))
|
||||
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);
|
||||
|
||||
@@ -316,58 +305,6 @@ meta_window_actor_thaw (MetaWindowActor *self)
|
||||
meta_window_actor_handle_updates (self);
|
||||
}
|
||||
|
||||
static void
|
||||
set_surface (MetaWindowActor *self,
|
||||
MetaSurfaceActor *surface)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->surface)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id);
|
||||
priv->repaint_scheduled_id = 0;
|
||||
g_signal_handler_disconnect (priv->surface, priv->allocation_changed_id);
|
||||
priv->allocation_changed_id = 0;
|
||||
clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
g_object_unref (priv->surface);
|
||||
}
|
||||
|
||||
priv->surface = surface;
|
||||
|
||||
if (priv->surface)
|
||||
{
|
||||
g_object_ref_sink (priv->surface);
|
||||
priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled",
|
||||
G_CALLBACK (surface_repaint_scheduled), self);
|
||||
priv->allocation_changed_id = g_signal_connect (priv->surface, "allocation-changed",
|
||||
G_CALLBACK (surface_allocation_changed_notify), self);
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
|
||||
/* If the previous surface actor was frozen, start out
|
||||
* frozen as well... */
|
||||
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
|
||||
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_update_surface (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
|
||||
if (window->surface)
|
||||
surface_actor = window->surface->surface_actor;
|
||||
else if (!meta_is_wayland_compositor ())
|
||||
surface_actor = meta_surface_actor_x11_new (window);
|
||||
else
|
||||
surface_actor = NULL;
|
||||
|
||||
set_surface (self, surface_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_constructed (GObject *object)
|
||||
{
|
||||
@@ -377,7 +314,20 @@ meta_window_actor_constructed (GObject *object)
|
||||
|
||||
priv->screen = window->screen;
|
||||
|
||||
meta_window_actor_update_surface (self);
|
||||
if (!priv->surface)
|
||||
{
|
||||
if (window->surface)
|
||||
priv->surface = window->surface->surface_actor;
|
||||
else
|
||||
priv->surface = meta_surface_actor_x11_new (window);
|
||||
g_object_ref_sink (priv->surface);
|
||||
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
|
||||
g_signal_connect_object (priv->surface, "allocation-changed",
|
||||
G_CALLBACK (surface_allocation_changed_notify), self, 0);
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
|
||||
meta_window_actor_update_opacity (self);
|
||||
|
||||
@@ -420,7 +370,10 @@ meta_window_actor_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&priv->window);
|
||||
|
||||
set_surface (self, NULL);
|
||||
/*
|
||||
* Release the extra reference we took on the actor.
|
||||
*/
|
||||
g_clear_object (&priv->surface);
|
||||
|
||||
G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -449,6 +402,9 @@ meta_window_actor_set_property (GObject *object,
|
||||
{
|
||||
case PROP_META_WINDOW:
|
||||
priv->window = g_value_dup_object (value);
|
||||
|
||||
g_signal_connect_object (priv->window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
g_signal_connect_object (priv->window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self, 0);
|
||||
break;
|
||||
@@ -670,12 +626,6 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
|
||||
|
||||
meta_window_actor_get_shape_bounds (self, &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)
|
||||
{
|
||||
cairo_rectangle_int_t shadow_bounds;
|
||||
@@ -691,6 +641,9 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
|
||||
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
|
||||
}
|
||||
|
||||
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
|
||||
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
|
||||
|
||||
origin.x = bounds.x;
|
||||
origin.y = bounds.y;
|
||||
origin.z = 0.0f;
|
||||
@@ -785,26 +738,21 @@ 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,
|
||||
* or NULL if no texture is shown yet, because the window is not mapped.
|
||||
* Gets the ClutterActor that is used to display the contents of the window
|
||||
*
|
||||
* Return value: (transfer none): the #ClutterActor for the contents
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_window_actor_get_texture (MetaWindowActor *self)
|
||||
{
|
||||
if (self->priv->surface)
|
||||
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
|
||||
else
|
||||
return NULL;
|
||||
return CLUTTER_ACTOR (meta_surface_actor_get_texture (self->priv->surface));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_get_surface:
|
||||
* @self: a #MetaWindowActor
|
||||
*
|
||||
* Gets the MetaSurfaceActor that draws the content of this window,
|
||||
* or NULL if there is no surface yet associated with this window.
|
||||
* Gets the MetaSurfaceActor that draws the content of this window
|
||||
*
|
||||
* Return value: (transfer none): the #MetaSurfaceActor for the contents
|
||||
*/
|
||||
@@ -903,12 +851,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
|
||||
if (!priv->repaint_scheduled)
|
||||
{
|
||||
gboolean is_obscured;
|
||||
|
||||
if (priv->surface)
|
||||
is_obscured = meta_surface_actor_is_obscured (priv->surface);
|
||||
else
|
||||
is_obscured = FALSE;
|
||||
gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface);
|
||||
|
||||
/* A frame was marked by the client without actually doing any
|
||||
* damage or any unobscured, or while we had the window frozen
|
||||
@@ -924,12 +867,9 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1102,10 +1042,7 @@ gboolean
|
||||
meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
if (priv->surface)
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
else
|
||||
return FALSE;
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1113,8 +1050,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1232,11 +1167,13 @@ meta_window_actor_show (MetaWindowActor *self,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (info->switch_workspace_in_progress ||
|
||||
if (priv->redecorating ||
|
||||
info->switch_workspace_in_progress ||
|
||||
event == 0 ||
|
||||
!start_simple_effect (self, event))
|
||||
{
|
||||
clutter_actor_show (CLUTTER_ACTOR (self));
|
||||
priv->redecorating = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1471,7 +1408,6 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1561,12 +1497,11 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->surface)
|
||||
meta_surface_actor_process_damage (priv->surface,
|
||||
event->area.x,
|
||||
event->area.y,
|
||||
event->area.width,
|
||||
event->area.height);
|
||||
meta_surface_actor_process_damage (priv->surface,
|
||||
event->area.x,
|
||||
event->area.y,
|
||||
event->area.width,
|
||||
event->area.height);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1714,25 +1649,22 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
||||
if (mask_texture)
|
||||
cogl_object_unref (mask_texture);
|
||||
cogl_object_unref (mask_texture);
|
||||
|
||||
g_free (mask_data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_shape_region (MetaWindowActor *self)
|
||||
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -1743,11 +1675,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;
|
||||
@@ -1758,43 +1690,34 @@ meta_window_actor_update_shape_region (MetaWindowActor *self)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self)
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
{
|
||||
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)
|
||||
if (priv->window->frame != NULL && priv->window->input_region != 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_rectangle (region, &client_area);
|
||||
cairo_region_translate (region, client_area.x, client_area.y);
|
||||
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);
|
||||
}
|
||||
else if (priv->window->shape_region != NULL ||
|
||||
priv->window->input_region != NULL)
|
||||
else if (priv->window->input_region != NULL)
|
||||
{
|
||||
if (priv->window->shape_region != NULL)
|
||||
{
|
||||
region = cairo_region_copy (priv->window->shape_region);
|
||||
|
||||
if (priv->window->input_region != NULL)
|
||||
cairo_region_intersect (region, priv->window->input_region);
|
||||
}
|
||||
else
|
||||
region = cairo_region_reference (priv->window->input_region);
|
||||
region = cairo_region_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);
|
||||
@@ -1810,9 +1733,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
|
||||
if (argb32 && priv->window->opaque_region != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t client_area;
|
||||
MetaFrameBorders borders;
|
||||
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
|
||||
/* The opaque region is defined to be a part of the
|
||||
* window which ARGB32 will always paint with opaque
|
||||
@@ -1825,7 +1748,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, client_area.x, client_area.y);
|
||||
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
|
||||
cairo_region_intersect (opaque_region, priv->shape_region);
|
||||
}
|
||||
else if (argb32)
|
||||
@@ -1841,15 +1764,27 @@ 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_window_actor_update_shape_region (self);
|
||||
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);
|
||||
|
||||
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
meta_window_actor_update_input_region (self);
|
||||
meta_window_actor_update_input_region (self, &client_area);
|
||||
meta_window_actor_update_opaque_region (self);
|
||||
}
|
||||
|
||||
@@ -2069,8 +2004,7 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
if (priv->surface)
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (self->priv->surface), window->opacity);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -39,7 +39,6 @@
|
||||
#define SWITCH_TIMEOUT 500
|
||||
|
||||
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
|
||||
#define SCREEN_TILE_PREVIEW_DATA_KEY "MCCP-Default-screen-tile-preview-data"
|
||||
|
||||
#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ())
|
||||
#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
|
||||
@@ -68,7 +67,6 @@ struct _MetaDefaultPluginClass
|
||||
};
|
||||
|
||||
static GQuark actor_data_quark = 0;
|
||||
static GQuark screen_tile_preview_data_quark = 0;
|
||||
|
||||
static void start (MetaPlugin *plugin);
|
||||
static void minimize (MetaPlugin *plugin,
|
||||
@@ -99,12 +97,6 @@ static void kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void kill_switch_workspace (MetaPlugin *plugin);
|
||||
|
||||
static void show_tile_preview (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
static void hide_tile_preview (MetaPlugin *plugin);
|
||||
|
||||
static void confirm_display_change (MetaPlugin *plugin);
|
||||
|
||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
|
||||
@@ -151,15 +143,6 @@ typedef struct
|
||||
} EffectCompleteData;
|
||||
|
||||
|
||||
typedef struct _ScreenTilePreview
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
GdkRGBA *preview_color;
|
||||
|
||||
MetaRectangle tile_rect;
|
||||
} ScreenTilePreview;
|
||||
|
||||
static void
|
||||
meta_default_plugin_dispose (GObject *object)
|
||||
{
|
||||
@@ -220,8 +203,6 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
plugin_class->unmaximize = unmaximize;
|
||||
plugin_class->destroy = destroy;
|
||||
plugin_class->switch_workspace = switch_workspace;
|
||||
plugin_class->show_tile_preview = show_tile_preview;
|
||||
plugin_class->hide_tile_preview = hide_tile_preview;
|
||||
plugin_class->plugin_info = plugin_info;
|
||||
plugin_class->kill_window_effects = kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = kill_switch_workspace;
|
||||
@@ -768,82 +749,6 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
meta_plugin_destroy_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tile preview private data accessor
|
||||
*/
|
||||
static void
|
||||
free_screen_tile_preview (gpointer data)
|
||||
{
|
||||
ScreenTilePreview *preview = data;
|
||||
|
||||
if (G_LIKELY (preview != NULL)) {
|
||||
clutter_actor_destroy (preview->actor);
|
||||
g_slice_free (ScreenTilePreview, preview);
|
||||
}
|
||||
}
|
||||
|
||||
static ScreenTilePreview *
|
||||
get_screen_tile_preview (MetaScreen *screen)
|
||||
{
|
||||
ScreenTilePreview *preview = g_object_get_qdata (G_OBJECT (screen), screen_tile_preview_data_quark);
|
||||
|
||||
if (G_UNLIKELY (screen_tile_preview_data_quark == 0))
|
||||
screen_tile_preview_data_quark = g_quark_from_static_string (SCREEN_TILE_PREVIEW_DATA_KEY);
|
||||
|
||||
if (G_UNLIKELY (!preview))
|
||||
{
|
||||
preview = g_slice_new0 (ScreenTilePreview);
|
||||
|
||||
preview->actor = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (preview->actor, CLUTTER_COLOR_Blue);
|
||||
clutter_actor_set_opacity (preview->actor, 100);
|
||||
|
||||
clutter_actor_add_child (meta_get_window_group_for_screen (screen), preview->actor);
|
||||
g_object_set_qdata_full (G_OBJECT (screen),
|
||||
screen_tile_preview_data_quark, preview,
|
||||
free_screen_tile_preview);
|
||||
}
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
static void
|
||||
show_tile_preview (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
ScreenTilePreview *preview = get_screen_tile_preview (screen);
|
||||
ClutterActor *window_actor;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_VISIBLE (preview->actor)
|
||||
&& preview->tile_rect.x == tile_rect->x
|
||||
&& preview->tile_rect.y == tile_rect->y
|
||||
&& preview->tile_rect.width == tile_rect->width
|
||||
&& preview->tile_rect.height == tile_rect->height)
|
||||
return; /* nothing to do */
|
||||
|
||||
clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y);
|
||||
clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height);
|
||||
|
||||
clutter_actor_show (preview->actor);
|
||||
|
||||
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
|
||||
clutter_actor_lower (preview->actor, window_actor);
|
||||
|
||||
preview->tile_rect = *tile_rect;
|
||||
}
|
||||
|
||||
static void
|
||||
hide_tile_preview (MetaPlugin *plugin)
|
||||
{
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
ScreenTilePreview *preview = get_screen_tile_preview (screen);
|
||||
|
||||
clutter_actor_hide (preview->actor);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_switch_workspace (MetaPlugin *plugin)
|
||||
{
|
||||
|
@@ -425,9 +425,8 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
||||
window->decorated &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
@@ -492,17 +491,12 @@ 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);
|
||||
|
||||
orig_rect = info->orig;
|
||||
extend_by_frame (window, &orig_rect);
|
||||
|
||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
||||
meta_window_place (window, info->orig.x, info->orig.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
|
@@ -736,6 +736,31 @@ 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,6 +199,8 @@ 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);
|
||||
|
@@ -84,6 +84,14 @@ typedef enum {
|
||||
META_TILE_MAXIMIZED
|
||||
} MetaTileMode;
|
||||
|
||||
typedef enum {
|
||||
META_FOCUS_NONE = 0,
|
||||
META_FOCUS_X_CLIENT = 1,
|
||||
META_FOCUS_WAYLAND_CLIENT = 2,
|
||||
META_FOCUS_NO_FOCUS_WINDOW = 3,
|
||||
META_FOCUS_STAGE = 4
|
||||
} MetaFocusType;
|
||||
|
||||
struct _MetaDisplay
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -117,6 +125,7 @@ struct _MetaDisplay
|
||||
* like the no_focus_window or the stage X window. */
|
||||
Window focus_xwindow;
|
||||
gulong focus_serial;
|
||||
MetaFocusType focus_type;
|
||||
|
||||
/* last timestamp passed to XSetInputFocus */
|
||||
guint32 last_focus_time;
|
||||
@@ -215,6 +224,7 @@ struct _MetaDisplay
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
@@ -232,8 +242,8 @@ struct _MetaDisplay
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
/* Keybindings stuff */
|
||||
GHashTable *key_bindings;
|
||||
GHashTable *key_bindings_index;
|
||||
MetaKeyBinding *key_bindings;
|
||||
int n_key_bindings;
|
||||
int min_keycode;
|
||||
int max_keycode;
|
||||
KeySym *keymap;
|
||||
@@ -483,9 +493,10 @@ gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event);
|
||||
#endif /* HAVE_XI23 */
|
||||
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
Window window,
|
||||
guint32 timestamp);
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaFocusType type,
|
||||
Window window,
|
||||
guint32 timestamp);
|
||||
|
||||
#endif
|
||||
|
@@ -75,6 +75,14 @@
|
||||
#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
|
||||
*
|
||||
@@ -1295,6 +1303,10 @@ 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)
|
||||
{
|
||||
@@ -1363,6 +1375,13 @@ 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;
|
||||
|
||||
@@ -1414,20 +1433,6 @@ 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
|
||||
@@ -1677,19 +1682,13 @@ get_window_for_event (MetaDisplay *display,
|
||||
if (display->grab_op != META_GRAB_OP_NONE)
|
||||
return display->grab_window;
|
||||
|
||||
/* Always use the key focused window for key events. */
|
||||
switch (event->type)
|
||||
{
|
||||
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));
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (source))
|
||||
{
|
||||
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (source));
|
||||
g_assert (surface != NULL);
|
||||
return surface->window;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1747,11 +1746,12 @@ get_input_event (MetaDisplay *display,
|
||||
}
|
||||
|
||||
static void
|
||||
update_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us)
|
||||
update_focus_window (MetaDisplay *display,
|
||||
MetaFocusType type,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
|
||||
@@ -1759,6 +1759,7 @@ update_focus_window (MetaDisplay *display,
|
||||
display->focused_by_us = focused_by_us;
|
||||
|
||||
if (display->focus_xwindow == xwindow &&
|
||||
display->focus_type == type &&
|
||||
display->focus_window == window)
|
||||
return;
|
||||
|
||||
@@ -1781,14 +1782,25 @@ update_focus_window (MetaDisplay *display,
|
||||
meta_window_set_focused_internal (previous, FALSE);
|
||||
}
|
||||
|
||||
display->focus_type = type;
|
||||
display->focus_window = window;
|
||||
display->focus_xwindow = xwindow;
|
||||
|
||||
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);
|
||||
@@ -1797,7 +1809,8 @@ update_focus_window (MetaDisplay *display,
|
||||
{
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
|
||||
if (display->focus_type == META_FOCUS_NO_FOCUS_WINDOW ||
|
||||
display->focus_type == META_FOCUS_STAGE)
|
||||
meta_wayland_compositor_set_input_focus (compositor, NULL);
|
||||
else if (window && window->surface)
|
||||
meta_wayland_compositor_set_input_focus (compositor, window);
|
||||
@@ -1839,11 +1852,12 @@ timestamp_too_old (MetaDisplay *display,
|
||||
}
|
||||
|
||||
static void
|
||||
request_xserver_input_focus_change (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *meta_window,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
request_xserver_input_focus_change (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaFocusType type,
|
||||
MetaWindow *meta_window,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
gulong serial;
|
||||
|
||||
@@ -1876,6 +1890,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
|
||||
meta_display_ungrab (display);
|
||||
|
||||
update_focus_window (display,
|
||||
type,
|
||||
meta_window,
|
||||
xwindow,
|
||||
serial,
|
||||
@@ -1897,9 +1912,12 @@ handle_window_focus_event (MetaDisplay *display,
|
||||
unsigned long serial)
|
||||
{
|
||||
MetaWindow *focus_window;
|
||||
MetaFocusType type;
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
const char *window_type;
|
||||
|
||||
type = META_FOCUS_NONE;
|
||||
|
||||
/* Note the event can be on either the window or the frame,
|
||||
* we focus the frame for shaded windows
|
||||
*/
|
||||
@@ -1911,14 +1929,26 @@ handle_window_focus_event (MetaDisplay *display,
|
||||
window_type = "frame window";
|
||||
else
|
||||
window_type = "unknown client window";
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
type = META_FOCUS_WAYLAND_CLIENT;
|
||||
else
|
||||
type = META_FOCUS_X_CLIENT;
|
||||
}
|
||||
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
|
||||
window_type = "no_focus_window";
|
||||
{
|
||||
window_type = "no_focus_window";
|
||||
type = META_FOCUS_NO_FOCUS_WINDOW;
|
||||
}
|
||||
else if (meta_display_screen_for_root (display, event->event))
|
||||
window_type = "root window";
|
||||
else
|
||||
window_type = "unknown window";
|
||||
|
||||
/* Don't change type if we don't know the new window */
|
||||
if (type == META_FOCUS_NONE)
|
||||
type = display->focus_type;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on %s 0x%lx (%s) "
|
||||
"mode %s detail %s serial %lu\n",
|
||||
@@ -2003,6 +2033,7 @@ handle_window_focus_event (MetaDisplay *display,
|
||||
display->server_focus_serial == display->focus_serial))
|
||||
{
|
||||
update_focus_window (display,
|
||||
type,
|
||||
focus_window,
|
||||
focus_window ? focus_window->xwindow : None,
|
||||
display->server_focus_serial,
|
||||
@@ -2031,6 +2062,9 @@ 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 ();
|
||||
@@ -2064,7 +2098,7 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
@@ -2082,76 +2116,79 @@ 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;
|
||||
|
||||
/* 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.
|
||||
/* 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 = (event->button.modifier_state & grab_mask) == 0;
|
||||
fully_modified = grab_mask && (event->button.modifier_state & grab_mask) == grab_mask;
|
||||
|
||||
if (unmodified && window && window->have_focus_click_grab)
|
||||
if (unmodified ||
|
||||
event->button.button == 1)
|
||||
{
|
||||
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
|
||||
/* 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 (window->type != META_WINDOW_DOCK)
|
||||
if (!frame_was_receiver)
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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_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;
|
||||
/* you can move on alt-click but not on
|
||||
* the click-to-focus
|
||||
*/
|
||||
if (!unmodified)
|
||||
begin_move = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ())
|
||||
else if (!unmodified && ((int) event->button.button == meta_prefs_get_mouse_button_resize ()))
|
||||
{
|
||||
if (window->has_resize_func)
|
||||
{
|
||||
@@ -2199,10 +2236,8 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||
else if ((int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
@@ -2214,29 +2249,27 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == 1)
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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 (grab_op_should_block_mouse_events (display->grab_op))
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
@@ -2250,7 +2283,7 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
}
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
@@ -2284,10 +2317,6 @@ 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))
|
||||
@@ -2302,10 +2331,11 @@ 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;
|
||||
MetaScreen *screen;
|
||||
gboolean frame_was_receiver;
|
||||
|
||||
if (input_event == NULL)
|
||||
return FALSE;
|
||||
@@ -2313,8 +2343,242 @@ 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;
|
||||
@@ -2370,11 +2634,12 @@ handle_input_xevent (MetaDisplay *display,
|
||||
if (!window)
|
||||
{
|
||||
/* Check if the window is a root window. */
|
||||
if (enter_event->root != enter_event->event)
|
||||
MetaScreen *screen =
|
||||
meta_display_screen_for_root(display,
|
||||
enter_event->event);
|
||||
if (screen == NULL)
|
||||
break;
|
||||
|
||||
screen = meta_display_screen_for_root (display, enter_event->root);
|
||||
|
||||
if (enter_event->evtype == XI_FocusIn &&
|
||||
enter_event->mode == XINotifyDetailNone)
|
||||
{
|
||||
@@ -2400,9 +2665,7 @@ handle_input_xevent (MetaDisplay *display,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Don't send FocusIn / FocusOut to Clutter */
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -2988,8 +3251,9 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
MetaMonitorManager *monitor;
|
||||
MetaScreen *screen;
|
||||
|
||||
#if 0
|
||||
meta_spew_event (display, event);
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
if (dump_events)
|
||||
meta_spew_event (display, event);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
@@ -3018,6 +3282,7 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
|
||||
display->focus_window->desc);
|
||||
update_focus_window (display,
|
||||
META_FOCUS_NONE,
|
||||
meta_display_lookup_x_window (display, display->server_focus_window),
|
||||
display->server_focus_window,
|
||||
display->server_focus_serial,
|
||||
@@ -3265,7 +3530,8 @@ event_get_time (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED const char*
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
const char*
|
||||
meta_event_detail_to_string (int d)
|
||||
{
|
||||
const char *detail = "???";
|
||||
@@ -3301,8 +3567,10 @@ meta_event_detail_to_string (int d)
|
||||
|
||||
return detail;
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
G_GNUC_UNUSED const char*
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
const char*
|
||||
meta_event_mode_to_string (int m)
|
||||
{
|
||||
const char *mode = "???";
|
||||
@@ -3324,8 +3592,10 @@ meta_event_mode_to_string (int m)
|
||||
|
||||
return mode;
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
G_GNUC_UNUSED static const char*
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static const char*
|
||||
stack_mode_to_string (int mode)
|
||||
{
|
||||
switch (mode)
|
||||
@@ -3344,9 +3614,11 @@ stack_mode_to_string (int mode)
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
G_GNUC_UNUSED static gint64
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static gint64
|
||||
sync_value_to_64 (const XSyncValue *value)
|
||||
{
|
||||
gint64 v;
|
||||
@@ -3356,8 +3628,10 @@ sync_value_to_64 (const XSyncValue *value)
|
||||
|
||||
return v;
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
G_GNUC_UNUSED static const char*
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static const char*
|
||||
alarm_state_to_string (XSyncAlarmState state)
|
||||
{
|
||||
switch (state)
|
||||
@@ -3372,9 +3646,12 @@ alarm_state_to_string (XSyncAlarmState state)
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void
|
||||
meta_spew_xi2_event (MetaDisplay *display,
|
||||
XIEvent *input_event,
|
||||
const char **name_p,
|
||||
@@ -3383,10 +3660,26 @@ 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;
|
||||
@@ -3411,6 +3704,34 @@ 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",
|
||||
@@ -3434,7 +3755,7 @@ meta_spew_xi2_event (MetaDisplay *display,
|
||||
*extra_p = extra;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
static void
|
||||
meta_spew_core_event (MetaDisplay *display,
|
||||
XEvent *event,
|
||||
const char **name_p,
|
||||
@@ -3658,7 +3979,7 @@ meta_spew_core_event (MetaDisplay *display,
|
||||
*extra_p = extra;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
static void
|
||||
meta_spew_event (MetaDisplay *display,
|
||||
XEvent *event)
|
||||
{
|
||||
@@ -3667,6 +3988,9 @@ 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 ||
|
||||
@@ -3696,16 +4020,18 @@ meta_spew_event (MetaDisplay *display,
|
||||
else
|
||||
winname = g_strdup_printf ("0x%lx", event->xany.window);
|
||||
|
||||
g_print ("%s on %s%s %s %sserial %lu\n", name, winname,
|
||||
extra ? ":" : "", extra ? extra : "",
|
||||
event->xany.send_event ? "SEND " : "",
|
||||
event->xany.serial);
|
||||
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_free (winname);
|
||||
|
||||
if (extra)
|
||||
g_free (extra);
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
MetaWindow*
|
||||
meta_display_lookup_x_window (MetaDisplay *display,
|
||||
@@ -4033,6 +4359,7 @@ 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;
|
||||
@@ -4069,6 +4396,16 @@ 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);
|
||||
@@ -4110,6 +4447,20 @@ 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) ||
|
||||
@@ -5600,6 +5951,8 @@ meta_display_set_input_focus_window (MetaDisplay *display,
|
||||
{
|
||||
request_xserver_input_focus_change (display,
|
||||
window->screen,
|
||||
window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND ?
|
||||
META_FOCUS_WAYLAND_CLIENT : META_FOCUS_X_CLIENT,
|
||||
window,
|
||||
focus_frame ? window->frame->xwindow : window->xwindow,
|
||||
timestamp);
|
||||
@@ -5622,13 +5975,15 @@ meta_display_request_take_focus (MetaDisplay *display,
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
Window window,
|
||||
guint32 timestamp)
|
||||
meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaFocusType type,
|
||||
Window window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (display,
|
||||
screen,
|
||||
type,
|
||||
NULL,
|
||||
window,
|
||||
timestamp);
|
||||
@@ -5641,6 +5996,7 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display,
|
||||
{
|
||||
request_xserver_input_focus_change (display,
|
||||
screen,
|
||||
META_FOCUS_NO_FOCUS_WINDOW,
|
||||
NULL,
|
||||
screen->no_focus_window,
|
||||
timestamp);
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#include <gio/gio.h>
|
||||
#include <meta/keybindings.h>
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
struct _MetaKeyHandler
|
||||
{
|
||||
char *name;
|
||||
@@ -48,48 +47,9 @@ struct _MetaKeyBinding
|
||||
KeyCode keycode;
|
||||
unsigned int mask;
|
||||
MetaVirtualModifier modifiers;
|
||||
gint flags;
|
||||
MetaKeyHandler *handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *combos;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
void meta_display_init_keys (MetaDisplay *display);
|
||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
@@ -117,8 +77,5 @@ gboolean meta_prefs_add_keybinding (const char *name,
|
||||
|
||||
gboolean meta_prefs_remove_keybinding (const char *name);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
|
||||
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
|
||||
|
||||
#include <config.h>
|
||||
#include <meta/main.h>
|
||||
@@ -53,7 +53,7 @@
|
||||
#include "session.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib-unix.h>
|
||||
@@ -190,7 +190,6 @@ static gboolean opt_replace_wm;
|
||||
static gboolean opt_disable_sm;
|
||||
static gboolean opt_sync;
|
||||
static gboolean opt_wayland;
|
||||
static gboolean opt_display_server;
|
||||
|
||||
static GOptionEntry meta_options[] = {
|
||||
{
|
||||
@@ -234,11 +233,6 @@ static GOptionEntry meta_options[] = {
|
||||
N_("Run as a wayland compositor"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_display_server,
|
||||
N_("Run as a full display server, rather than nested")
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -407,7 +401,8 @@ meta_init (void)
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
meta_set_debugging (TRUE);
|
||||
|
||||
if (opt_display_server)
|
||||
/* We consider running from mutter-launch equivalent to running from bare metal. */
|
||||
if (getenv ("WESTON_LAUNCHER_SOCK"))
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
|
||||
meta_set_is_wayland_compositor (opt_wayland);
|
||||
@@ -502,32 +497,6 @@ meta_register_with_session (void)
|
||||
g_free (opt_client_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
meta_activate_session (void)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_wayland_compositor_activate_session (compositor, &error))
|
||||
{
|
||||
g_warning ("Could not activate session: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_run: (skip)
|
||||
*
|
||||
|
@@ -43,7 +43,4 @@ 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,7 +39,6 @@
|
||||
#include <gbm.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
@@ -570,9 +569,6 @@ 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))
|
||||
@@ -1078,13 +1074,12 @@ get_pointer_position_gdk (int *x,
|
||||
GdkScreen *gscreen;
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
gdevice = gdk_device_manager_get_client_pointer (gmanager);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1100,12 +1095,9 @@ get_pointer_position_clutter (int *x,
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
*x = point.x;
|
||||
*y = point.y;
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1147,12 +1139,3 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
update_hw_cursor (tracker);
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
@@ -653,10 +653,8 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
||||
{
|
||||
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
|
||||
|
||||
g_object_ref (monitor);
|
||||
g_hash_table_remove (monitor->watches,
|
||||
GUINT_TO_POINTER (id));
|
||||
g_object_unref (monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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_OFF;
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "util-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "monitor-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
|
||||
|
@@ -57,6 +57,7 @@
|
||||
|
||||
#define KEY_OVERLAY_KEY "overlay-key"
|
||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
||||
#define KEY_NO_TAB_POPUP "no-tab-popup"
|
||||
|
||||
/* These are the different schemas we are keeping
|
||||
* a GSettings instance for */
|
||||
@@ -111,6 +112,8 @@ static char **workspace_names = NULL;
|
||||
|
||||
static gboolean workspaces_only_on_primary = FALSE;
|
||||
|
||||
static gboolean no_tab_popup = FALSE;
|
||||
|
||||
static char *iso_next_group_option = NULL;
|
||||
|
||||
static void handle_preference_update_enum (GSettings *settings,
|
||||
@@ -362,6 +365,13 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&workspaces_only_on_primary,
|
||||
},
|
||||
{
|
||||
{ KEY_NO_TAB_POPUP,
|
||||
SCHEMA_MUTTER,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
},
|
||||
&no_tab_popup,
|
||||
},
|
||||
{
|
||||
{ "auto-maximize",
|
||||
SCHEMA_MUTTER,
|
||||
@@ -1803,6 +1813,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
|
||||
return "WORKSPACES_ONLY_ON_PRIMARY";
|
||||
|
||||
case META_PREF_NO_TAB_POPUP:
|
||||
return "NO_TAB_POPUP";
|
||||
|
||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||
return "DRAGGABLE_BORDER_WIDTH";
|
||||
|
||||
@@ -1856,7 +1869,7 @@ init_bindings (void)
|
||||
pref = g_new0 (MetaKeyPref, 1);
|
||||
pref->name = g_strdup ("overlay-key");
|
||||
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
|
||||
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
|
||||
pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
|
||||
pref->builtin = 1;
|
||||
|
||||
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
|
||||
@@ -1866,7 +1879,7 @@ static gboolean
|
||||
update_binding (MetaKeyPref *binding,
|
||||
gchar **strokes)
|
||||
{
|
||||
GSList *old_combos, *a, *b;
|
||||
GSList *old_bindings, *a, *b;
|
||||
gboolean changed;
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
@@ -1878,8 +1891,8 @@ update_binding (MetaKeyPref *binding,
|
||||
"Binding \"%s\" has new GSettings value\n",
|
||||
binding->name);
|
||||
|
||||
old_combos = binding->combos;
|
||||
binding->combos = NULL;
|
||||
old_bindings = binding->bindings;
|
||||
binding->bindings = NULL;
|
||||
|
||||
for (i = 0; strokes && strokes[i]; i++)
|
||||
{
|
||||
@@ -1920,17 +1933,17 @@ update_binding (MetaKeyPref *binding,
|
||||
combo->keysym = keysym;
|
||||
combo->keycode = keycode;
|
||||
combo->modifiers = mods;
|
||||
binding->combos = g_slist_prepend (binding->combos, combo);
|
||||
binding->bindings = g_slist_prepend (binding->bindings, combo);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
||||
binding->name, keysym, keycode, mods);
|
||||
}
|
||||
|
||||
binding->combos = g_slist_reverse (binding->combos);
|
||||
binding->bindings = g_slist_reverse (binding->bindings);
|
||||
|
||||
a = old_combos;
|
||||
b = binding->combos;
|
||||
a = old_bindings;
|
||||
b = binding->bindings;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((!a && b) || (a && !b))
|
||||
@@ -1955,7 +1968,7 @@ update_binding (MetaKeyPref *binding,
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free_full (old_combos, g_free);
|
||||
g_slist_free_full (old_bindings, g_free);
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -2090,7 +2103,7 @@ meta_prefs_add_keybinding (const char *name,
|
||||
pref->name = g_strdup (name);
|
||||
pref->settings = g_object_ref (settings);
|
||||
pref->action = action;
|
||||
pref->combos = NULL;
|
||||
pref->bindings = NULL;
|
||||
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
||||
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
||||
@@ -2154,6 +2167,11 @@ meta_prefs_remove_keybinding (const char *name)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_get_keybindings:
|
||||
*
|
||||
* Returns: (element-type MetaKeyPref) (transfer container):
|
||||
*/
|
||||
GList *
|
||||
meta_prefs_get_keybindings ()
|
||||
{
|
||||
@@ -2254,7 +2272,7 @@ meta_prefs_get_window_binding (const char *name,
|
||||
|
||||
if (pref->per_window)
|
||||
{
|
||||
GSList *s = pref->combos;
|
||||
GSList *s = pref->bindings;
|
||||
|
||||
while (s)
|
||||
{
|
||||
@@ -2302,6 +2320,25 @@ meta_prefs_get_workspaces_only_on_primary (void)
|
||||
return workspaces_only_on_primary;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_no_tab_popup (void)
|
||||
{
|
||||
return no_tab_popup;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_no_tab_popup (gboolean whether)
|
||||
{
|
||||
MetaBasePreference *pref;
|
||||
|
||||
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
|
||||
KEY_NO_TAB_POPUP, &pref))
|
||||
{
|
||||
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
meta_prefs_get_draggable_border_width (void)
|
||||
{
|
||||
|
@@ -64,6 +64,8 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
MetaTilePreview *tile_preview;
|
||||
|
||||
guint tile_preview_timeout_id;
|
||||
|
||||
@@ -149,9 +151,25 @@ void meta_screen_foreach_window (MetaScreen *scree
|
||||
|
||||
void meta_screen_update_cursor (MetaScreen *screen);
|
||||
|
||||
void meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
void meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_window);
|
||||
void meta_screen_tab_popup_forward (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_backward (MetaScreen *screen);
|
||||
MetaWindow* meta_screen_tab_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection);
|
||||
void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace);
|
||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
gboolean delay);
|
||||
void meta_screen_hide_tile_preview (MetaScreen *screen);
|
||||
void meta_screen_tile_preview_hide (MetaScreen *screen);
|
||||
|
||||
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one);
|
||||
|
@@ -43,7 +43,7 @@
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "core.h"
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
@@ -308,8 +308,6 @@ 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,
|
||||
@@ -762,6 +760,10 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
|
||||
screen->tab_popup = NULL;
|
||||
screen->ws_popup = NULL;
|
||||
screen->tile_preview = NULL;
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
screen->stack = meta_stack_new (screen);
|
||||
@@ -866,6 +868,9 @@ meta_screen_free (MetaScreen *screen,
|
||||
if (screen->tile_preview_timeout_id)
|
||||
g_source_remove (screen->tile_preview_timeout_id);
|
||||
|
||||
if (screen->tile_preview)
|
||||
meta_tile_preview_free (screen->tile_preview);
|
||||
|
||||
g_free (screen->screen_name);
|
||||
|
||||
g_object_unref (screen);
|
||||
@@ -1427,8 +1432,255 @@ meta_screen_update_cursor (MetaScreen *screen)
|
||||
screen->current_cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
GList *tab_list;
|
||||
GList *tmp;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (screen->tab_popup)
|
||||
return;
|
||||
|
||||
tab_list = meta_display_get_tab_list (screen->display,
|
||||
list_type,
|
||||
screen,
|
||||
screen->active_workspace);
|
||||
|
||||
len = g_list_length (tab_list);
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
tmp = tab_list;
|
||||
while (i < len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaRectangle r;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) window;
|
||||
entries[i].title = window->title;
|
||||
entries[i].icon = g_object_ref (window->icon);
|
||||
entries[i].blank = FALSE;
|
||||
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entries[i].demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||
!entries[i].hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_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)
|
||||
meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
{
|
||||
MetaScreen *screen = data;
|
||||
MetaWindow *window = screen->display->grab_window;
|
||||
@@ -1436,6 +1688,22 @@ meta_screen_update_tile_preview_timeout (gpointer data)
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
if (!screen->tile_preview)
|
||||
{
|
||||
Window xwindow;
|
||||
gulong create_serial;
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
screen->tile_preview = meta_tile_preview_new (screen->number);
|
||||
xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
|
||||
&create_serial);
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = xwindow;
|
||||
meta_stack_tracker_record_add (screen->stack_tracker,
|
||||
&stack_window,
|
||||
create_serial);
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
switch (window->tile_mode)
|
||||
@@ -1460,16 +1728,12 @@ meta_screen_update_tile_preview_timeout (gpointer data)
|
||||
if (needs_preview)
|
||||
{
|
||||
MetaRectangle tile_rect;
|
||||
int monitor;
|
||||
|
||||
monitor = meta_window_get_current_tile_monitor_number (window);
|
||||
meta_window_get_current_tile_area (window, &tile_rect);
|
||||
meta_compositor_show_tile_preview (screen->display->compositor,
|
||||
screen, window, &tile_rect, monitor);
|
||||
meta_tile_preview_show (screen->tile_preview, &tile_rect);
|
||||
}
|
||||
else
|
||||
meta_compositor_hide_tile_preview (screen->display->compositor,
|
||||
screen);
|
||||
meta_tile_preview_hide (screen->tile_preview);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1477,7 +1741,7 @@ meta_screen_update_tile_preview_timeout (gpointer data)
|
||||
#define TILE_PREVIEW_TIMEOUT_MS 200
|
||||
|
||||
void
|
||||
meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
gboolean delay)
|
||||
{
|
||||
if (delay)
|
||||
@@ -1487,7 +1751,7 @@ meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
|
||||
screen->tile_preview_timeout_id =
|
||||
g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
|
||||
meta_screen_update_tile_preview_timeout,
|
||||
meta_screen_tile_preview_update_timeout,
|
||||
screen);
|
||||
}
|
||||
else
|
||||
@@ -1495,18 +1759,18 @@ meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
if (screen->tile_preview_timeout_id > 0)
|
||||
g_source_remove (screen->tile_preview_timeout_id);
|
||||
|
||||
meta_screen_update_tile_preview_timeout ((gpointer)screen);
|
||||
meta_screen_tile_preview_update_timeout ((gpointer)screen);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_hide_tile_preview (MetaScreen *screen)
|
||||
meta_screen_tile_preview_hide (MetaScreen *screen)
|
||||
{
|
||||
if (screen->tile_preview_timeout_id > 0)
|
||||
g_source_remove (screen->tile_preview_timeout_id);
|
||||
|
||||
meta_compositor_hide_tile_preview (screen->display->compositor,
|
||||
screen);
|
||||
if (screen->tile_preview)
|
||||
meta_tile_preview_hide (screen->tile_preview);
|
||||
}
|
||||
|
||||
MetaWindow*
|
||||
@@ -1514,19 +1778,38 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one)
|
||||
{
|
||||
MetaWindow *window;
|
||||
int x, y;
|
||||
Window root_return, child_return;
|
||||
double root_x_return, root_y_return;
|
||||
double win_x_return, win_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_error_trap_push (screen->display);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
meta_error_trap_pop (screen->display);
|
||||
free (buttons.mask);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
not_this_one,
|
||||
x, y);
|
||||
root_x_return,
|
||||
root_y_return);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -1808,11 +2091,28 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
int x, y;
|
||||
Window root_return, child_return;
|
||||
double win_x_return, win_y_return;
|
||||
double root_x_return, root_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_screen_get_current_monitor_for_pos (screen, x, y);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
free (buttons.mask);
|
||||
|
||||
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
|
@@ -1041,7 +1041,7 @@ stack_tracker_event_received (MetaStackTracker *tracker,
|
||||
|
||||
if (op->any.serial < tracker->xserver_serial)
|
||||
{
|
||||
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
|
||||
g_warning ("Spurious X event received affecting stack; doing full re-query");
|
||||
resync_verified_stack_with_xserver_stack (tracker);
|
||||
meta_stack_tracker_dump (tracker);
|
||||
return;
|
||||
|
@@ -92,6 +92,7 @@ struct _MetaWindow
|
||||
char *icon_name;
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
MetaIconCache icon_cache;
|
||||
Pixmap wm_hints_pixmap;
|
||||
Pixmap wm_hints_mask;
|
||||
|
||||
@@ -651,7 +652,6 @@ void meta_window_handle_mouse_grab_op_xevent (MetaWindow *window,
|
||||
|
||||
GList* meta_window_get_workspaces (MetaWindow *window);
|
||||
|
||||
int meta_window_get_current_tile_monitor_number (MetaWindow *window);
|
||||
void meta_window_get_current_tile_area (MetaWindow *window,
|
||||
MetaRectangle *tile_area);
|
||||
|
||||
@@ -683,8 +683,9 @@ void meta_window_update_layer (MetaWindow *window);
|
||||
|
||||
void meta_window_recalc_features (MetaWindow *window);
|
||||
|
||||
void meta_window_set_type (MetaWindow *window,
|
||||
MetaWindowType type);
|
||||
/* 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_frame_size_changed (MetaWindow *window);
|
||||
|
||||
@@ -741,14 +742,9 @@ 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 _XOPEN_SOURCE 500 /* for gethostname() */
|
||||
#define _SVID_SOURCE /* for gethostname() */
|
||||
|
||||
#include <config.h>
|
||||
#include "window-props.h"
|
||||
@@ -237,6 +237,9 @@ 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);
|
||||
}
|
||||
|
||||
@@ -724,7 +727,7 @@ reload_net_wm_state (MetaWindow *window,
|
||||
meta_verbose ("Reloaded _NET_WM_STATE for %s\n",
|
||||
window->desc);
|
||||
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
meta_window_recalc_window_type (window);
|
||||
meta_window_recalc_features (window);
|
||||
}
|
||||
|
||||
@@ -1500,6 +1503,10 @@ 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,7 +38,6 @@
|
||||
#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"
|
||||
@@ -226,7 +225,7 @@ meta_window_x11_update_net_wm_type (MetaWindow *window)
|
||||
meta_XFree (str);
|
||||
}
|
||||
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
meta_window_recalc_window_type (window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -351,43 +350,11 @@ 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))
|
||||
{
|
||||
@@ -396,7 +363,17 @@ 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,
|
||||
@@ -411,10 +388,10 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
{
|
||||
if (n_rects > 1 ||
|
||||
(n_rects == 1 &&
|
||||
(rects[0].x != 0 ||
|
||||
rects[0].y != 0 ||
|
||||
rects[0].width != window->rect.width ||
|
||||
rects[0].height != window->rect.height)))
|
||||
(rects[0].x != x_bounding ||
|
||||
rects[0].y != y_bounding ||
|
||||
rects[0].width != w_bounding ||
|
||||
rects[0].height != h_bounding)))
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
|
||||
XFree (rects);
|
||||
@@ -674,19 +651,35 @@ meta_window_x11_property_notify (MetaWindow *window,
|
||||
static int
|
||||
query_pressed_buttons (MetaWindow *window)
|
||||
{
|
||||
ClutterModifierType mods;
|
||||
double x, y, query_root_x, query_root_y;
|
||||
Window root, child;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int button = 0;
|
||||
|
||||
meta_cursor_tracker_get_pointer (window->screen->cursor_tracker,
|
||||
NULL, NULL, &mods);
|
||||
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);
|
||||
|
||||
if (mods & CLUTTER_BUTTON1_MASK)
|
||||
if (meta_error_trap_pop_with_return (window->display) != Success)
|
||||
goto out;
|
||||
|
||||
if (XIMaskIsSet (buttons.mask, Button1))
|
||||
button |= 1 << 1;
|
||||
if (mods & CLUTTER_BUTTON2_MASK)
|
||||
if (XIMaskIsSet (buttons.mask, Button2))
|
||||
button |= 1 << 2;
|
||||
if (mods & CLUTTER_BUTTON3_MASK)
|
||||
if (XIMaskIsSet (buttons.mask, Button3))
|
||||
button |= 1 << 3;
|
||||
|
||||
free (buttons.mask);
|
||||
|
||||
out:
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -872,7 +865,7 @@ meta_window_x11_client_message (MetaWindow *window,
|
||||
(action == _NET_WM_STATE_ADD) ||
|
||||
(action == _NET_WM_STATE_TOGGLE && !window->wm_state_modal);
|
||||
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
meta_window_recalc_window_type (window);
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
@@ -1460,11 +1453,6 @@ 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);
|
||||
@@ -1497,7 +1485,14 @@ meta_window_x11_new (MetaDisplay *display,
|
||||
existing_wm_state,
|
||||
effect,
|
||||
&attrs);
|
||||
meta_window_set_surface_mapped (window, TRUE);
|
||||
|
||||
/* When running as an X compositor, we can simply show the window now.
|
||||
*
|
||||
* When running as a Wayland compositor, we need to wait until we see
|
||||
* the Wayland surface appear. We will later call meta_window_set_surface_mapped()
|
||||
* to show the window in our in our set_surface_id implementation */
|
||||
if (!meta_is_wayland_compositor ())
|
||||
meta_window_set_surface_mapped (window, TRUE);
|
||||
|
||||
meta_error_trap_pop (display); /* pop the XSync()-reducing trap */
|
||||
return window;
|
||||
@@ -1506,114 +1501,3 @@ 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,8 +35,6 @@ 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,6 +233,8 @@ 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);
|
||||
@@ -816,6 +818,7 @@ _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;
|
||||
@@ -990,9 +993,6 @@ _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);
|
||||
|
||||
@@ -1177,6 +1177,9 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
if (!window->override_redirect)
|
||||
meta_stack_add (window->screen->stack,
|
||||
window);
|
||||
else if (window->screen->tile_preview != NULL &&
|
||||
meta_tile_preview_get_xwindow (window->screen->tile_preview, NULL) == xwindow)
|
||||
window->layer = META_LAYER_NORMAL;
|
||||
else
|
||||
window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */
|
||||
|
||||
@@ -1217,9 +1220,6 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
set_net_wm_state (window);
|
||||
}
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_add_window (screen->display->compositor, window);
|
||||
|
||||
/* Sync stack changes */
|
||||
meta_stack_thaw (window->screen->stack);
|
||||
|
||||
@@ -2772,8 +2772,8 @@ meta_window_show (MetaWindow *window)
|
||||
break;
|
||||
}
|
||||
|
||||
meta_compositor_show_window (window->display->compositor,
|
||||
window, effect);
|
||||
meta_compositor_add_window (window->display->compositor, window);
|
||||
meta_compositor_show_window (window->display->compositor, window, effect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3117,9 +3117,6 @@ 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");
|
||||
@@ -3372,7 +3369,7 @@ meta_window_tile (MetaWindow *window)
|
||||
directions = META_MAXIMIZE_VERTICAL;
|
||||
|
||||
meta_window_maximize_internal (window, directions, NULL);
|
||||
meta_screen_update_tile_preview (window->screen, FALSE);
|
||||
meta_screen_tile_preview_update (window->screen, FALSE);
|
||||
|
||||
if (window->display->compositor)
|
||||
{
|
||||
@@ -3605,13 +3602,10 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
set_net_wm_state (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));
|
||||
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
|
||||
@@ -3714,9 +3708,6 @@ 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");
|
||||
}
|
||||
}
|
||||
@@ -3773,9 +3764,6 @@ 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");
|
||||
}
|
||||
}
|
||||
@@ -5091,7 +5079,6 @@ meta_window_move_resize_wayland (MetaWindow *window,
|
||||
|
||||
meta_window_move_resize_internal (window, flags, NorthWestGravity,
|
||||
x, y, width, height);
|
||||
save_user_window_placement (window);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5661,37 +5648,6 @@ 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)
|
||||
{
|
||||
@@ -6790,13 +6746,25 @@ meta_window_update_icon_now (MetaWindow *window)
|
||||
icon = NULL;
|
||||
mini_icon = NULL;
|
||||
|
||||
if (read_icons (window->screen,
|
||||
window->xwindow,
|
||||
window->wm_hints_pixmap,
|
||||
window->wm_hints_mask,
|
||||
&window->icon))
|
||||
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 (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");
|
||||
@@ -7049,7 +7017,122 @@ meta_window_update_struts (MetaWindow *window)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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
|
||||
meta_window_type_changed (MetaWindow *window)
|
||||
{
|
||||
gboolean old_decorated = window->decorated;
|
||||
@@ -7082,17 +7165,6 @@ 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)
|
||||
{
|
||||
@@ -7734,7 +7806,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
|
||||
/* Titlebar can't be offscreen if there is no titlebar... */
|
||||
if (!window->frame)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
/* Get the rectangle corresponding to the titlebar */
|
||||
meta_window_get_frame_rect (window, &titlebar_rect);
|
||||
@@ -8036,7 +8108,7 @@ update_move (MetaWindow *window,
|
||||
* trigger it unwittingly, e.g. when shaking loose the window or moving
|
||||
* it to another monitor.
|
||||
*/
|
||||
meta_screen_update_tile_preview (window->screen,
|
||||
meta_screen_tile_preview_update (window->screen,
|
||||
window->tile_mode != META_TILE_NONE);
|
||||
|
||||
meta_window_get_client_root_coords (window, &old);
|
||||
@@ -8415,6 +8487,98 @@ 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)
|
||||
{
|
||||
@@ -8485,6 +8649,96 @@ 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)
|
||||
@@ -8702,20 +8956,6 @@ meta_window_get_work_area_all_monitors (MetaWindow *window,
|
||||
window->desc, area->x, area->y, area->width, area->height);
|
||||
}
|
||||
|
||||
int
|
||||
meta_window_get_current_tile_monitor_number (MetaWindow *window)
|
||||
{
|
||||
int tile_monitor_number = window->tile_monitor_number;
|
||||
|
||||
if (tile_monitor_number < 0)
|
||||
{
|
||||
meta_warning ("%s called with an invalid monitor number; using 0 instead\n", G_STRFUNC);
|
||||
tile_monitor_number = 0;
|
||||
}
|
||||
|
||||
return tile_monitor_number;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_get_current_tile_area (MetaWindow *window,
|
||||
MetaRectangle *tile_area)
|
||||
@@ -8724,7 +8964,12 @@ meta_window_get_current_tile_area (MetaWindow *window,
|
||||
|
||||
g_return_if_fail (window->tile_mode != META_TILE_NONE);
|
||||
|
||||
tile_monitor_number = meta_window_get_current_tile_monitor_number (window);
|
||||
tile_monitor_number = window->tile_monitor_number;
|
||||
if (tile_monitor_number < 0)
|
||||
{
|
||||
meta_warning ("%s called with an invalid monitor number; using 0 instead\n", G_STRFUNC);
|
||||
tile_monitor_number = 0;
|
||||
}
|
||||
|
||||
meta_window_get_work_area_for_monitor (window, tile_monitor_number, tile_area);
|
||||
|
||||
@@ -8749,34 +8994,6 @@ 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)
|
||||
{
|
||||
@@ -10139,8 +10356,7 @@ meta_window_set_transient_for (MetaWindow *window,
|
||||
meta_window_propagate_focus_appearance (window, FALSE);
|
||||
|
||||
/* may now be a dialog */
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
meta_window_x11_recalc_window_type (window);
|
||||
meta_window_recalc_window_type (window);
|
||||
|
||||
if (!window->constructing)
|
||||
{
|
||||
@@ -10266,15 +10482,25 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
MetaWindow *window = focus_data->window;
|
||||
MetaDisplay *display = window->display;
|
||||
MetaScreen *screen = window->screen;
|
||||
int root_x, root_y;
|
||||
Window root, child;
|
||||
double root_x, root_y, x, y;
|
||||
guint32 timestamp;
|
||||
ClutterActor *child;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
|
||||
goto out;
|
||||
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&root_x, &root_y, NULL);
|
||||
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);
|
||||
|
||||
if (root_x != focus_data->pointer_x ||
|
||||
root_y != focus_data->pointer_y)
|
||||
@@ -10284,15 +10510,17 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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))
|
||||
/* 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))
|
||||
goto out;
|
||||
|
||||
window =
|
||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
NULL, root_x, root_y);
|
||||
None, root_x, root_y);
|
||||
|
||||
if (window == NULL)
|
||||
goto out;
|
||||
|
@@ -214,6 +214,21 @@ 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,
|
||||
@@ -228,10 +243,7 @@ typedef enum
|
||||
META_GRAB_OP_CLICKING_UNSTICK,
|
||||
|
||||
/* Special grab op when the compositor asked for a grab */
|
||||
META_GRAB_OP_COMPOSITOR,
|
||||
|
||||
/* For when a client takes a popup grab */
|
||||
META_GRAB_OP_WAYLAND_CLIENT,
|
||||
META_GRAB_OP_COMPOSITOR
|
||||
} MetaGrabOp;
|
||||
|
||||
/**
|
||||
@@ -492,6 +504,12 @@ 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,8 +66,6 @@ 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,
|
||||
@@ -123,12 +121,4 @@ void meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
void meta_compositor_flash_screen (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
|
||||
void meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
void meta_compositor_hide_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_H */
|
||||
|
@@ -28,7 +28,6 @@ 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);
|
||||
|
@@ -158,11 +158,6 @@ struct _MetaPluginClass
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
void (*show_tile_preview) (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
void (*hide_tile_preview) (MetaPlugin *plugin);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::kill_window_effects:
|
||||
|
@@ -62,6 +62,7 @@
|
||||
* @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
|
||||
*/
|
||||
@@ -99,6 +100,7 @@ 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;
|
||||
@@ -161,6 +163,9 @@ 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);
|
||||
@@ -199,6 +204,8 @@ 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
|
||||
@@ -294,6 +301,8 @@ 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,
|
||||
@@ -371,6 +380,20 @@ 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
|
||||
@@ -388,14 +411,45 @@ 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 --display-server
|
||||
Exec=mutter-launch -- mutter --wayland
|
||||
NoDisplay=true
|
||||
# name of loadable control center module
|
||||
X-GNOME-WMSettingsModule=metacity
|
||||
|
224
src/ui/draw-workspace.c
Normal file
224
src/ui/draw-workspace.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/* -*- 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);
|
||||
|
||||
}
|
59
src/ui/draw-workspace.h
Normal file
59
src/ui/draw-workspace.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*- 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,6 +44,8 @@
|
||||
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,
|
||||
@@ -132,6 +134,9 @@ 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;
|
||||
@@ -226,7 +231,6 @@ 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);
|
||||
@@ -518,26 +522,13 @@ MetaFrames*
|
||||
meta_frames_new (int screen_number)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
MetaFrames *frames;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
|
||||
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;
|
||||
return g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* In order to use a style with a window it has to be attached to that
|
||||
@@ -644,6 +635,22 @@ 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)
|
||||
|
963
src/ui/tabpopup.c
Normal file
963
src/ui/tabpopup.c
Normal file
@@ -0,0 +1,963 @@
|
||||
/* -*- 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;
|
||||
}
|
65
src/ui/tabpopup.h
Normal file
65
src/ui/tabpopup.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- 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
|
||||
|
196
src/ui/tile-preview.c
Normal file
196
src/ui/tile-preview.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter tile-preview marks the area a window will *ehm* snap to */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 Florian Müllner
|
||||
*
|
||||
* 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 <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#include "tile-preview.h"
|
||||
#include "core.h"
|
||||
|
||||
#define OUTLINE_WIDTH 5 /* frame width in non-composite case */
|
||||
|
||||
|
||||
struct _MetaTilePreview {
|
||||
GtkWidget *preview_window;
|
||||
gulong create_serial;
|
||||
|
||||
GdkRGBA *preview_color;
|
||||
|
||||
MetaRectangle tile_rect;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
meta_tile_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaTilePreview *preview = user_data;
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
/* Fill the preview area with a transparent color */
|
||||
gdk_cairo_set_source_rgba (cr, preview->preview_color);
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
|
||||
/* Use the opaque color for the border */
|
||||
cairo_set_source_rgb (cr,
|
||||
preview->preview_color->red,
|
||||
preview->preview_color->green,
|
||||
preview->preview_color->blue);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
0.5, 0.5,
|
||||
preview->tile_rect.width - 1,
|
||||
preview->tile_rect.height - 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MetaTilePreview *
|
||||
meta_tile_preview_new (int screen_number)
|
||||
{
|
||||
MetaTilePreview *preview;
|
||||
GdkScreen *screen;
|
||||
GtkStyleContext *context;
|
||||
GtkWidgetPath *path;
|
||||
guchar selection_alpha = 0xFF;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (), screen_number);
|
||||
|
||||
preview = g_new (MetaTilePreview, 1);
|
||||
|
||||
preview->preview_window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (preview->preview_window), screen);
|
||||
gtk_widget_set_app_paintable (preview->preview_window, TRUE);
|
||||
|
||||
preview->preview_color = NULL;
|
||||
|
||||
preview->tile_rect.x = preview->tile_rect.y = 0;
|
||||
preview->tile_rect.width = preview->tile_rect.height = 0;
|
||||
|
||||
gtk_widget_set_visual (preview->preview_window,
|
||||
gdk_screen_get_rgba_visual (screen));
|
||||
|
||||
path = gtk_widget_path_new ();
|
||||
gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
|
||||
|
||||
context = gtk_style_context_new ();
|
||||
gtk_style_context_set_path (context, path);
|
||||
gtk_style_context_add_class (context,
|
||||
GTK_STYLE_CLASS_RUBBERBAND);
|
||||
|
||||
gtk_widget_path_free (path);
|
||||
|
||||
gtk_style_context_get (context, GTK_STATE_FLAG_SELECTED,
|
||||
"background-color", &preview->preview_color,
|
||||
NULL);
|
||||
|
||||
/* The background-color for the .rubberband class should probably
|
||||
* contain the correct alpha value - unfortunately, at least for now
|
||||
* it doesn't. Hopefully the following workaround can be removed
|
||||
* when GtkIconView gets ported to GtkStyleContext.
|
||||
*/
|
||||
gtk_style_context_get_style (context,
|
||||
"selection-box-alpha", &selection_alpha,
|
||||
NULL);
|
||||
preview->preview_color->alpha = (double)selection_alpha / 0xFF;
|
||||
|
||||
g_object_unref (context);
|
||||
|
||||
/* We make an assumption that XCreateWindow will be the first operation
|
||||
* when calling gtk_widget_realize() (via gdk_window_new()), or that it
|
||||
* is at least "close enough".
|
||||
*/
|
||||
preview->create_serial = XNextRequest (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
gtk_widget_realize (preview->preview_window);
|
||||
g_signal_connect (preview->preview_window, "draw",
|
||||
G_CALLBACK (meta_tile_preview_draw), preview);
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
void
|
||||
meta_tile_preview_free (MetaTilePreview *preview)
|
||||
{
|
||||
gtk_widget_destroy (preview->preview_window);
|
||||
|
||||
if (preview->preview_color)
|
||||
gdk_rgba_free (preview->preview_color);
|
||||
|
||||
g_free (preview);
|
||||
}
|
||||
|
||||
void
|
||||
meta_tile_preview_show (MetaTilePreview *preview,
|
||||
MetaRectangle *tile_rect)
|
||||
{
|
||||
GdkWindow *window;
|
||||
GdkRectangle old_rect;
|
||||
|
||||
if (gtk_widget_get_visible (preview->preview_window)
|
||||
&& preview->tile_rect.x == tile_rect->x
|
||||
&& preview->tile_rect.y == tile_rect->y
|
||||
&& preview->tile_rect.width == tile_rect->width
|
||||
&& preview->tile_rect.height == tile_rect->height)
|
||||
return; /* nothing to do */
|
||||
|
||||
gtk_widget_show (preview->preview_window);
|
||||
window = gtk_widget_get_window (preview->preview_window);
|
||||
meta_core_lower_beneath_grab_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
GDK_WINDOW_XID (window),
|
||||
gtk_get_current_event_time ());
|
||||
|
||||
old_rect.x = old_rect.y = 0;
|
||||
old_rect.width = preview->tile_rect.width;
|
||||
old_rect.height = preview->tile_rect.height;
|
||||
|
||||
gdk_window_invalidate_rect (window, &old_rect, FALSE);
|
||||
|
||||
preview->tile_rect = *tile_rect;
|
||||
|
||||
gdk_window_move_resize (window,
|
||||
preview->tile_rect.x, preview->tile_rect.y,
|
||||
preview->tile_rect.width, preview->tile_rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_tile_preview_hide (MetaTilePreview *preview)
|
||||
{
|
||||
gtk_widget_hide (preview->preview_window);
|
||||
}
|
||||
|
||||
Window
|
||||
meta_tile_preview_get_xwindow (MetaTilePreview *preview,
|
||||
gulong *create_serial)
|
||||
{
|
||||
GdkWindow *window = gtk_widget_get_window (preview->preview_window);
|
||||
|
||||
if (create_serial)
|
||||
*create_serial = preview->create_serial;
|
||||
|
||||
return GDK_WINDOW_XID (window);
|
||||
}
|
36
src/ui/tile-preview.h
Normal file
36
src/ui/tile-preview.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Meta tile preview */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 Florian Müllner
|
||||
*
|
||||
* 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_TILE_PREVIEW_H
|
||||
#define META_TILE_PREVIEW_H
|
||||
|
||||
#include <meta/boxes.h>
|
||||
|
||||
typedef struct _MetaTilePreview MetaTilePreview;
|
||||
|
||||
MetaTilePreview *meta_tile_preview_new (int screen_number);
|
||||
void meta_tile_preview_free (MetaTilePreview *preview);
|
||||
void meta_tile_preview_show (MetaTilePreview *preview,
|
||||
MetaRectangle *rect);
|
||||
void meta_tile_preview_hide (MetaTilePreview *preview);
|
||||
Window meta_tile_preview_get_xwindow (MetaTilePreview *preview,
|
||||
gulong *create_serial);
|
||||
|
||||
#endif /* META_TILE_PREVIEW_H */
|
80
src/ui/ui.c
80
src/ui/ui.c
@@ -295,12 +295,9 @@ meta_ui_new (Display *xdisplay,
|
||||
g_assert (gdisplay == gdk_display_get_default ());
|
||||
|
||||
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
|
||||
/* GTK+ needs the frame-sync protocol to work in order to properly
|
||||
* handle style changes. This means that the dummy widget we create
|
||||
* 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.
|
||||
*/
|
||||
/* 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_widget_show (GTK_WIDGET (ui->frames));
|
||||
|
||||
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
|
||||
@@ -598,6 +595,76 @@ 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)
|
||||
@@ -705,6 +772,7 @@ void
|
||||
meta_ui_set_current_theme (const char *name)
|
||||
{
|
||||
meta_theme_set_current (name);
|
||||
meta_invalidate_default_icons ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -143,6 +143,9 @@ 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);
|
||||
|
||||
@@ -175,4 +178,7 @@ int meta_ui_get_drag_threshold (MetaUI *ui);
|
||||
|
||||
MetaUIDirection meta_ui_get_direction (void);
|
||||
|
||||
#include "tabpopup.h"
|
||||
#include "tile-preview.h"
|
||||
|
||||
#endif
|
||||
|
@@ -48,7 +48,7 @@ data_offer_accept (struct wl_client *client,
|
||||
* this be a wl_data_device request? */
|
||||
|
||||
if (offer->source)
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
offer->source->accept (offer->source, serial, 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)
|
||||
wl_data_source_send_send (offer->source->resource, mime_type, fd);
|
||||
|
||||
close (fd);
|
||||
offer->source->send (offer->source, mime_type, fd);
|
||||
else
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -82,8 +82,7 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
|
||||
if (offer->source)
|
||||
wl_list_remove (&offer->source_destroy_listener.link);
|
||||
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
free (offer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -100,9 +99,13 @@ static struct wl_resource *
|
||||
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
MetaWaylandDataOffer *offer;
|
||||
char **p;
|
||||
|
||||
offer = malloc (sizeof *offer);
|
||||
if (offer == NULL)
|
||||
return NULL;
|
||||
|
||||
offer->source = source;
|
||||
offer->source_destroy_listener.notify = destroy_offer_data_source;
|
||||
|
||||
@@ -315,12 +318,8 @@ data_device_start_drag (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
|
||||
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 client has implicit grab on the origin
|
||||
* surface that matches the given time. */
|
||||
|
||||
/* FIXME: Check that the data source type array isn't empty. */
|
||||
|
||||
@@ -333,7 +332,6 @@ 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)
|
||||
{
|
||||
@@ -377,7 +375,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial)
|
||||
@@ -391,7 +389,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
|
||||
if (seat->selection_data_source)
|
||||
{
|
||||
wl_data_source_send_cancelled (seat->selection_data_source->resource);
|
||||
seat->selection_data_source->cancel (seat->selection_data_source);
|
||||
wl_list_remove (&seat->selection_data_source_listener.link);
|
||||
seat->selection_data_source = NULL;
|
||||
}
|
||||
@@ -451,21 +449,47 @@ static const struct wl_data_device_interface data_device_interface = {
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source = wl_container_of (resource, source, resource);
|
||||
char **p;
|
||||
|
||||
wl_array_for_each (p, &source->mime_types) free (*p);
|
||||
|
||||
wl_array_release (&source->mime_types);
|
||||
}
|
||||
|
||||
g_slice_free (MetaWaylandDataSource, source);
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
create_data_source (struct wl_client *client,
|
||||
struct wl_resource *resource, guint32 id)
|
||||
{
|
||||
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
source = malloc (sizeof *source);
|
||||
if (source == NULL)
|
||||
{
|
||||
wl_resource_post_no_memory (resource);
|
||||
return;
|
||||
}
|
||||
|
||||
source->resource = wl_resource_create (client, &wl_data_source_interface,
|
||||
MIN (META_WL_DATA_SOURCE_VERSION,
|
||||
@@ -473,6 +497,10 @@ 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,4 +33,10 @@ 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,6 +142,20 @@ 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)
|
||||
{
|
||||
@@ -203,26 +217,28 @@ err_keymap_str:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
release_focus (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
|
||||
keyboard->focus_resource = NULL;
|
||||
keyboard->focus_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
|
||||
|
||||
keyboard->focus_surface = NULL;
|
||||
|
||||
if (keyboard->focus_resource)
|
||||
{
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
keyboard->focus_resource = NULL;
|
||||
}
|
||||
release_focus (keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
|
||||
|
||||
keyboard->focus_resource = NULL;
|
||||
release_focus (keyboard);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -281,6 +297,31 @@ 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)
|
||||
@@ -496,13 +537,26 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
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);
|
||||
/* 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_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
|
||||
keyboard->focus_serial = serial;
|
||||
@@ -536,6 +590,85 @@ 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,7 +47,6 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct _MetaWaylandKeyboardGrabInterface
|
||||
{
|
||||
@@ -72,6 +71,14 @@ 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
|
||||
@@ -142,6 +149,13 @@ 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,31 +49,34 @@
|
||||
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "xdg-shell-server-protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
static void
|
||||
release_focus (MetaWaylandPointer *pointer)
|
||||
{
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
|
||||
pointer->focus_resource = NULL;
|
||||
pointer->focus_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
|
||||
pointer->focus_surface = NULL;
|
||||
|
||||
if (pointer->focus_resource)
|
||||
{
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
release_focus (pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
|
||||
|
||||
pointer->focus_resource = NULL;
|
||||
release_focus (pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -299,7 +302,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
{
|
||||
/* Do nothing. */
|
||||
release_focus (pointer);
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
@@ -398,6 +401,61 @@ 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;
|
||||
|
||||
@@ -472,18 +530,19 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
||||
|
||||
wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link)
|
||||
{
|
||||
meta_wayland_surface_popup_done (popup->surface);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
@@ -523,8 +582,6 @@ 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;
|
||||
@@ -532,19 +589,6 @@ 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;
|
||||
@@ -553,12 +597,10 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
popup->grab = grab;
|
||||
popup->surface = surface;
|
||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||
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_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
|
||||
wl_list_insert (&grab->all_popups, &popup->link);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@@ -85,6 +85,11 @@ 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,6 +21,7 @@
|
||||
#define META_WAYLAND_PRIVATE_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <glib.h>
|
||||
@@ -30,7 +31,7 @@
|
||||
#include "meta-weston-launch.h"
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-wayland-versions.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
@@ -90,8 +91,30 @@ 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,53 +276,42 @@ static void
|
||||
handle_scroll_event (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
wl_fixed_t x_value = 0, y_value = 0;
|
||||
enum wl_pointer_axis axis;
|
||||
wl_fixed_t value;
|
||||
|
||||
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:
|
||||
y_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
|
||||
value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_DOWN:
|
||||
y_value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
|
||||
value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_LEFT:
|
||||
x_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
|
||||
value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_RIGHT:
|
||||
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);
|
||||
}
|
||||
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
|
||||
value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
if (seat->pointer.focus_resource)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource,
|
||||
clutter_event_get_time (event),
|
||||
axis,
|
||||
value);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@@ -43,6 +43,12 @@ 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,6 +82,7 @@ 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
|
||||
@@ -261,6 +262,9 @@ 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));
|
||||
@@ -291,7 +295,7 @@ actor_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaSurfaceActor *surface_actor = surface->surface_actor;
|
||||
MetaWaylandBuffer *buffer = pending->buffer;
|
||||
|
||||
if (buffer_changed && buffer)
|
||||
if (buffer_changed)
|
||||
{
|
||||
ensure_buffer_texture (buffer);
|
||||
meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
|
||||
@@ -336,6 +340,22 @@ 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
|
||||
@@ -361,6 +381,8 @@ 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
|
||||
@@ -552,16 +574,23 @@ const struct wl_surface_interface meta_wayland_surface_interface = {
|
||||
meta_wayland_surface_set_buffer_scale
|
||||
};
|
||||
|
||||
void
|
||||
meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface)
|
||||
static void
|
||||
unparent_actor (MetaWaylandSurface *surface)
|
||||
{
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
|
||||
ClutterActor *parent_actor;
|
||||
|
||||
parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
|
||||
clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor));
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface)
|
||||
{
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE);
|
||||
/* The window is being unmanaged. Unparent our surface actor
|
||||
* before the window actor is destroyed, as we need to hold
|
||||
* onto it... */
|
||||
unparent_actor (surface);
|
||||
|
||||
surface->window = NULL;
|
||||
}
|
||||
|
||||
@@ -620,17 +649,28 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
|
||||
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
|
||||
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
|
||||
|
||||
double_buffered_state_init (&surface->pending);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -640,22 +680,23 @@ 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,
|
||||
MetaWaylandSurface *surface,
|
||||
struct wl_resource *master_resource,
|
||||
guint32 id)
|
||||
wl_resource_destroy_func_t destructor)
|
||||
{
|
||||
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, surface, destructor);
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -682,10 +723,11 @@ xdg_shell_pong (struct wl_client *client,
|
||||
static void
|
||||
xdg_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_surface);
|
||||
destroy_surface_extension (xdg_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -700,7 +742,8 @@ xdg_surface_set_transient_for (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *parent_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWindow *transient_for = NULL;
|
||||
|
||||
if (parent_resource)
|
||||
@@ -720,7 +763,8 @@ xdg_surface_set_margin (struct wl_client *client,
|
||||
int32_t top_margin,
|
||||
int32_t bottom_margin)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.frame_extents_changed = TRUE;
|
||||
surface->pending.frame_extents.left = left_margin;
|
||||
@@ -734,7 +778,8 @@ xdg_surface_set_title (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
}
|
||||
@@ -744,7 +789,8 @@ xdg_surface_set_app_id (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *app_id)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
meta_window_set_wm_class (surface->window, app_id, app_id);
|
||||
}
|
||||
@@ -779,7 +825,8 @@ xdg_surface_move (struct wl_client *client,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
@@ -790,7 +837,7 @@ xdg_surface_move (struct wl_client *client,
|
||||
}
|
||||
|
||||
static MetaGrabOp
|
||||
grab_op_for_xdg_surface_resize_edge (int edge)
|
||||
grab_op_for_edge (int edge)
|
||||
{
|
||||
switch (edge)
|
||||
{
|
||||
@@ -824,14 +871,15 @@ xdg_surface_resize (struct wl_client *client,
|
||||
guint32 edges)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
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_xdg_surface_resize_edge (edges));
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -843,51 +891,55 @@ xdg_surface_set_output (struct wl_client *client,
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_request_change_state (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t state_type,
|
||||
uint32_t value,
|
||||
uint32_t serial)
|
||||
xdg_surface_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
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);
|
||||
}
|
||||
surface->pending.fullscreen.changed = TRUE;
|
||||
surface->pending.fullscreen.value = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_ack_change_state (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t state_type,
|
||||
uint32_t value,
|
||||
uint32_t serial)
|
||||
xdg_surface_unset_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
/* 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. */
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_minimized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
meta_window_minimize (surface->window);
|
||||
}
|
||||
@@ -901,8 +953,10 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
|
||||
xdg_surface_move,
|
||||
xdg_surface_resize,
|
||||
xdg_surface_set_output,
|
||||
xdg_surface_request_change_state,
|
||||
xdg_surface_ack_change_state,
|
||||
xdg_surface_set_fullscreen,
|
||||
xdg_surface_unset_fullscreen,
|
||||
xdg_surface_set_maximized,
|
||||
xdg_surface_unset_maximized,
|
||||
xdg_surface_set_minimized,
|
||||
};
|
||||
|
||||
@@ -914,12 +968,11 @@ 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,
|
||||
if (!create_surface_extension (&surface->xdg_surface, client, surface_resource, resource, id,
|
||||
META_XDG_SURFACE_VERSION,
|
||||
&xdg_surface_interface,
|
||||
&meta_wayland_xdg_surface_interface,
|
||||
xdg_surface_destructor,
|
||||
surface, resource, id))
|
||||
xdg_surface_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -927,17 +980,17 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
meta_wayland_surface_make_toplevel (surface);
|
||||
surface->window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_popup_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_popup);
|
||||
destroy_surface_extension (xdg_popup);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -970,12 +1023,11 @@ 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,
|
||||
if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id,
|
||||
META_XDG_POPUP_VERSION,
|
||||
&xdg_popup_interface,
|
||||
&meta_wayland_xdg_popup_interface,
|
||||
xdg_popup_destructor,
|
||||
surface, resource, id))
|
||||
xdg_popup_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -983,7 +1035,6 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
meta_wayland_surface_make_toplevel (surface);
|
||||
surface->window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
surface->window->rect.x = parent_surf->window->rect.x + x;
|
||||
surface->window->rect.y = parent_surf->window->rect.y + y;
|
||||
@@ -991,7 +1042,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
surface->window->placed = TRUE;
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
|
||||
meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
|
||||
surface->window->type = META_WINDOW_DROPDOWN_MENU;
|
||||
meta_window_type_changed (surface->window);
|
||||
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
}
|
||||
@@ -1057,264 +1109,13 @@ 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)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
|
||||
|
||||
destroy_surface_extension (&surface->gtk_surface);
|
||||
destroy_surface_extension (gtk_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1327,7 +1128,8 @@ set_dbus_properties (struct wl_client *client,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
|
||||
|
||||
/* Broken client, let it die instead of us */
|
||||
if (!surface->window)
|
||||
@@ -1357,12 +1159,11 @@ get_gtk_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->gtk_surface,
|
||||
if (!create_surface_extension (&surface->gtk_surface, client, surface_resource, resource, id,
|
||||
META_GTK_SURFACE_VERSION,
|
||||
>k_surface_interface,
|
||||
&meta_wayland_gtk_surface_interface,
|
||||
gtk_surface_destructor,
|
||||
surface, resource, id))
|
||||
gtk_surface_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1444,20 +1245,15 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface)
|
||||
|
||||
if (surface->sub.synchronous)
|
||||
commit_double_buffered_state (surface, pending_surface_state);
|
||||
}
|
||||
|
||||
static void
|
||||
unparent_actor (MetaWaylandSurface *surface)
|
||||
{
|
||||
ClutterActor *parent_actor;
|
||||
parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
|
||||
clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor));
|
||||
double_buffered_state_reset (pending_surface_state);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_subsurface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
if (surface->sub.parent)
|
||||
{
|
||||
@@ -1469,7 +1265,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
double_buffered_state_destroy (&surface->sub.pending_surface_state);
|
||||
destroy_surface_extension (&surface->subsurface);
|
||||
destroy_surface_extension (subsurface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1485,7 +1281,8 @@ wl_subsurface_set_position (struct wl_client *client,
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
surface->sub.pending_x = x;
|
||||
surface->sub.pending_y = y;
|
||||
@@ -1535,7 +1332,8 @@ wl_subsurface_place_above (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *sibling_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
|
||||
|
||||
if (!is_valid_sibling (surface, sibling))
|
||||
@@ -1557,7 +1355,8 @@ wl_subsurface_place_below (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *sibling_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
|
||||
|
||||
if (!is_valid_sibling (surface, sibling))
|
||||
@@ -1578,7 +1377,10 @@ static void
|
||||
wl_subsurface_set_sync (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface =
|
||||
wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
surface->sub.synchronous = TRUE;
|
||||
}
|
||||
@@ -1587,7 +1389,10 @@ static void
|
||||
wl_subsurface_set_desync (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface =
|
||||
wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
if (surface->sub.synchronous)
|
||||
subsurface_parent_surface_committed (surface);
|
||||
@@ -1633,12 +1438,11 @@ 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,
|
||||
if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id,
|
||||
META_GTK_SURFACE_VERSION,
|
||||
&wl_subsurface_interface,
|
||||
&meta_wayland_subsurface_interface,
|
||||
wl_subsurface_destructor,
|
||||
surface, resource, id))
|
||||
wl_subsurface_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1684,11 +1488,6 @@ 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,
|
||||
@@ -1710,58 +1509,6 @@ 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
|
||||
@@ -1782,23 +1529,16 @@ void
|
||||
meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
guint32 serial)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
if (xdg_shell == NULL)
|
||||
{
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
|
||||
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
|
||||
return;
|
||||
}
|
||||
|
||||
xdg_shell_send_ping (xdg_shell, serial);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1807,16 +1547,3 @@ 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,6 +41,12 @@ struct _MetaWaylandBuffer
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint changed : 1;
|
||||
guint value : 1;
|
||||
} MetaWaylandStateFlag;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* wl_surface.attach */
|
||||
@@ -61,11 +67,15 @@ 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
|
||||
@@ -76,7 +86,6 @@ struct _MetaWaylandSurface
|
||||
MetaWindow *window;
|
||||
MetaWaylandSurfaceExtension xdg_surface;
|
||||
MetaWaylandSurfaceExtension xdg_popup;
|
||||
MetaWaylandSurfaceExtension wl_shell_surface;
|
||||
MetaWaylandSurfaceExtension gtk_surface;
|
||||
MetaWaylandSurfaceExtension subsurface;
|
||||
|
||||
@@ -98,8 +107,6 @@ struct _MetaWaylandSurface
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
uint32_t state_changed_serial;
|
||||
|
||||
/* All the pending state, that wl_surface.commit will apply. */
|
||||
MetaWaylandDoubleBufferedState pending;
|
||||
};
|
||||
@@ -111,16 +118,11 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
|
||||
guint32 id,
|
||||
guint32 version);
|
||||
|
||||
void meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_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);
|
||||
@@ -129,7 +131,4 @@ 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,7 +37,6 @@
|
||||
/* 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
|
||||
@@ -53,10 +52,9 @@
|
||||
#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,8 +643,6 @@ 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 ();
|
||||
@@ -730,22 +728,7 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring VT switch keybinding, not running as display server");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
|
||||
GError **error)
|
||||
{
|
||||
if (compositor->launcher)
|
||||
{
|
||||
return meta_launcher_activate_vt (compositor->launcher, -1, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring activate_session, not running as display server");
|
||||
g_debug ("Ignoring VT switch keybinding, not running as VT manager");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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,8 +41,6 @@
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-weston-launch.h"
|
||||
|
||||
struct _MetaLauncher
|
||||
@@ -181,11 +179,11 @@ meta_launcher_set_drm_fd (MetaLauncher *self,
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
@@ -234,17 +232,6 @@ 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
|
||||
@@ -264,13 +251,6 @@ 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)
|
||||
{
|
||||
@@ -374,6 +354,8 @@ 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);
|
||||
|
||||
@@ -387,10 +369,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -410,7 +388,7 @@ meta_launcher_free (MetaLauncher *launcher)
|
||||
|
||||
gboolean
|
||||
meta_launcher_activate_vt (MetaLauncher *launcher,
|
||||
signed char vt,
|
||||
int vt,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_activate_vt message;
|
||||
|
@@ -29,10 +29,18 @@ MetaLauncher *meta_launcher_new (void);
|
||||
void meta_launcher_free (MetaLauncher *self);
|
||||
|
||||
gboolean meta_launcher_activate_vt (MetaLauncher *self,
|
||||
signed char vt,
|
||||
int number,
|
||||
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,19 +47,10 @@ 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);
|
||||
meta_window_set_surface_mapped (window, TRUE);
|
||||
}
|
||||
|
||||
static const struct xserver_interface xserver_implementation = {
|
||||
|
@@ -80,7 +80,6 @@ struct weston_launch {
|
||||
struct termios terminal_attributes;
|
||||
int kb_mode;
|
||||
enum vt_state vt_state;
|
||||
unsigned vt;
|
||||
|
||||
int drm_fd;
|
||||
};
|
||||
@@ -275,7 +274,6 @@ 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;
|
||||
@@ -287,13 +285,7 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
|
||||
message = msg->msg_iov->iov_base;
|
||||
|
||||
/* 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);
|
||||
reply.ret = ioctl(wl->tty, VT_ACTIVATE, message->vt);
|
||||
if (reply.ret < 0)
|
||||
reply.ret = -errno;
|
||||
|
||||
@@ -339,13 +331,6 @@ 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",
|
||||
@@ -354,6 +339,15 @@ 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;
|
||||
@@ -560,7 +554,7 @@ setup_tty(struct weston_launch *wl)
|
||||
struct stat buf;
|
||||
struct termios raw_attributes;
|
||||
struct vt_mode mode = { 0 };
|
||||
char *session;
|
||||
char *session, *tty;
|
||||
char path[PATH_MAX];
|
||||
int ok;
|
||||
|
||||
@@ -568,12 +562,43 @@ setup_tty(struct weston_launch *wl)
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current session");
|
||||
|
||||
ok = sd_session_get_vt(session, &wl->vt);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current TTY");
|
||||
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.
|
||||
|
||||
snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
|
||||
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
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
|
||||
error(1, -ok, "could not determine current TTY");
|
||||
|
||||
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;
|
||||
signed char vt;
|
||||
int vt;
|
||||
};
|
||||
|
||||
struct weston_launcher_reply {
|
||||
|
Reference in New Issue
Block a user