Compare commits

..

16 Commits

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

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

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

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

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

The dedicated event processing meant for frames in src/ui/ui.c
now hooks to the display connection through
meta_display_events_x11_add_func(), added to let all event filters
run and stop processing at a single point.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
321cd5d85f ui: Remove XI_TouchBegin handling from window frame event handlers
This is now unnecessary as only pointer events are selected, so pointer
emulation will take care of sending only pointer events.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ae91de5d03 frame: Only select for ButtonPress/Release/Motion/Crossing
Touch events are largely ignored on GdkEvent emulation, so only
make frames receive pointer events, only the pointer emulating
touch will be reported, and any other further touches will be
ignored, which is about the behavior we want. This makes window
dragging possible again on touch.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
7247b8d81b backend-x11: Remove pointless goto
The function is not as complex as needing that, plus it always jumped
anytime bypass_clutter is TRUE, so make all conditional code depend on
that.
2014-06-25 15:17:12 +02:00
73 changed files with 6194 additions and 5765 deletions

11
.gitignore vendored
View File

@@ -43,7 +43,6 @@ POTFILES
po/*.pot
libmutter.pc
mutter
mutter-restart-helper
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
@@ -52,6 +51,16 @@ testasyncgetprop
testboxes
testgradient
m4/*
mutter-grayscale
mutter-mag
mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]

21
NEWS
View File

@@ -1,24 +1,3 @@
3.13.4
======
* Fix move/resize operations for wayland clients [Marek; #731237]
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
* Handle keysyms without the XF86 prefix [Owen; #727993]
* Add touch gesture support [Carlos]
* Fix a deadlock when exiting [Owen; #733068]
* Add framework for restarting the compositor with nice visuals
[Owen; #733026]
* Toggle seat capabilities on VT switch [Carlos; #733563]
* Misc bug fixes [Florian, Owen; #732695, #732350]
Contributors:
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
Enrico Nicoletto [pt_BR]
3.13.3
======
* Improve behavior of window buttons with compositor menus [Florian; #731058]

View File

@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [4])
m4_define([mutter_micro_version], [3])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -72,18 +72,17 @@ CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gio-unix-2.0 >= 2.25.10
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
xcursor
$CLUTTER_PACKAGE >= 1.19.5
$CLUTTER_PACKAGE >= 1.17.5
clutter-wayland-1.0
clutter-wayland-compositor-1.0
clutter-egl-1.0
cogl-1.0 >= 1.17.1
libinput
wayland-server >= 1.4.93
upower-glib >= 0.99.0
gnome-desktop-3.0

3456
po/el.po

File diff suppressed because it is too large Load Diff

888
po/gl.po

File diff suppressed because it is too large Load Diff

1010
po/lt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1291
po/ru.po

File diff suppressed because it is too large Load Diff

View File

@@ -10,8 +10,6 @@ AM_CPPFLAGS = \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
@@ -154,8 +152,8 @@ libmutter_la_SOURCES = \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/meta-gesture-tracker.c \
core/meta-gesture-tracker-private.h \
core/gesture-tracker.c \
core/gesture-tracker-private.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@@ -167,7 +165,6 @@ libmutter_la_SOURCES = \
core/screen-private.h \
meta/screen.h \
meta/types.h \
core/restart.c \
core/stack.c \
core/stack.h \
core/stack-tracker.c \
@@ -317,10 +314,6 @@ bin_PROGRAMS=mutter
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
libexec_PROGRAMS = mutter-restart-helper
mutter_restart_helper_SOURCES = core/restart-helper.c
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)

View File

@@ -23,6 +23,8 @@
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <gbm.h>
#include "meta-cursor.h"
#include "meta-cursor-renderer.h"
@@ -30,6 +32,7 @@
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
MetaCursorRenderer *renderer;
gboolean is_showing;

View File

@@ -44,6 +44,9 @@
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
@@ -57,12 +60,10 @@ static guint signals[LAST_SIGNAL];
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
if (!tracker->is_showing)
return NULL;
if (display->grab_op == META_GRAB_OP_NONE)
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
{
if (tracker->has_window_cursor)
return tracker->window_cursor;
@@ -96,9 +97,6 @@ sync_cursor (MetaCursorTracker *tracker)
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
MetaBackend *backend = meta_get_backend ();
self->renderer = meta_backend_get_cursor_renderer (backend);
self->is_showing = TRUE;
}
@@ -131,9 +129,47 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
}
static MetaCursorTracker *
meta_cursor_tracker_new (void)
make_wayland_cursor_tracker (MetaScreen *screen)
{
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
MetaBackend *backend = meta_get_backend ();
MetaWaylandCompositor *compositor;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->pointer.cursor_tracker = self;
meta_cursor_tracker_update_position (self, 0, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
static MetaCursorTracker *
meta_cursor_tracker_new (MetaScreen *screen)
{
if (meta_is_wayland_compositor ())
return make_wayland_cursor_tracker (screen);
else
return make_x11_cursor_tracker (screen);
}
static MetaCursorTracker *_cursor_tracker;
@@ -150,7 +186,7 @@ MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new ();
_cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker;
}
@@ -171,13 +207,12 @@ gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
@@ -208,7 +243,6 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
@@ -218,7 +252,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (tracker->xfixes_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;

View File

@@ -60,7 +60,7 @@ typedef struct {
gboolean enabled;
MetaRectangle rect;
float refresh_rate;
MetaMonitorTransform transform;
enum wl_output_transform transform;
gboolean is_primary;
gboolean is_presentation;
@@ -656,20 +656,20 @@ handle_text (GMarkupParseContext *context,
else if (strcmp (parser->output_field, "rotation") == 0)
{
if (strncmp (text, "normal", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
else if (strncmp (text, "left", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_90;
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
else if (strncmp (text, "upside_down", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_180;
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
else if (strncmp (text, "right", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_270;
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
else
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid rotation type %.*s", (int)text_len, text);
}
else if (strcmp (parser->output_field, "reflect_x") == 0)
parser->output.transform += read_bool (text, text_len, error) ?
META_MONITOR_TRANSFORM_FLIPPED : 0;
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
else if (strcmp (parser->output_field, "reflect_y") == 0)
{
/* FIXME (look at the rotation map in monitor.c) */
@@ -1115,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[0].is_primary = TRUE;
return ret;
@@ -1167,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[j].is_primary = FALSE;
ret->outputs[j].is_presentation = FALSE;
}
@@ -1202,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = (output == primary);
/* Disable outputs that would go beyond framebuffer limits */
@@ -1250,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = TRUE;
}
else
@@ -1512,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
output->rect.x,
output->rect.y,
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no");
}
@@ -1621,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
}
static gboolean
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
MetaMonitorTransform transform,
MetaOutput *output)
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
enum wl_output_transform transform,
MetaOutput *output)
{
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);

View File

@@ -27,7 +27,7 @@
#include "meta-monitor-manager-dummy.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
{
@@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
@@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].winsys_id = 1;
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");

View File

@@ -125,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
*/
info.is_presentation = TRUE;
info.in_fullscreen = -1;
info.winsys_id = 0;
info.output_id = 0;
g_array_append_val (monitor_infos, info);
@@ -156,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
if (output->is_primary || info->winsys_id == 0)
info->winsys_id = output->winsys_id;
if (output->is_primary || info->output_id == 0)
info->output_id = output->output_id;
if (info->is_primary)
manager->primary_monitor_index = info->number;
@@ -477,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j);
@@ -560,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
(gint64)output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs,
output->name,
@@ -667,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
int new_mode, x, y;
int new_screen_width, new_screen_height;
guint transform;
guint output_index;
guint output_id;
GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial)
@@ -694,6 +694,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
MetaOutput *first_output;
MetaCRTC *crtc;
MetaMonitorMode *mode;
guint output_id;
crtc_info = g_slice_new (MetaCRTCInfo);
crtc_info->outputs = g_ptr_array_new ();
@@ -755,8 +756,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0;
}
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -767,18 +768,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->transform = transform;
first_output = NULL;
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
{
MetaOutput *output;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (!output_can_config (output, crtc, mode))
{
@@ -823,12 +824,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
g_variant_iter_init (&output_iter, outputs);
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
@@ -837,7 +838,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
output_info = g_slice_new0 (MetaOutputInfo);
output_info->output = &manager->outputs[output_index];
output_info->output = &manager->outputs[output_id];
if (g_variant_lookup (properties, "primary", "b", &primary))
output_info->is_primary = primary;
@@ -908,7 +909,7 @@ static gboolean
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation,
guint serial,
guint output_index,
guint output_id,
gint value)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
@@ -922,14 +923,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE;
}
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (value < 0 || value > 100)
{

View File

@@ -42,6 +42,7 @@
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#include <wayland-server.h>
#include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h"
@@ -59,23 +60,12 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef enum {
META_MONITOR_TRANSFORM_NORMAL,
META_MONITOR_TRANSFORM_90,
META_MONITOR_TRANSFORM_180,
META_MONITOR_TRANSFORM_270,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_270,
} MetaMonitorTransform;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong winsys_id;
glong output_id;
char *name;
char *vendor;
char *product;
@@ -124,7 +114,7 @@ struct _MetaCRTC
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
MetaMonitorTransform transform;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
@@ -172,14 +162,14 @@ struct _MetaMonitorInfo
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to a winsys_id of a MetaOutput.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong winsys_id;
glong output_id;
};
/*
@@ -195,7 +185,7 @@ struct _MetaCRTCInfo {
MetaMonitorMode *mode;
int x;
int y;
MetaMonitorTransform transform;
enum wl_output_transform transform;
GPtrArray *outputs;
};
@@ -349,7 +339,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}

View File

@@ -40,6 +40,8 @@
#include <meta/errors.h>
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
@@ -257,7 +259,7 @@ find_output_by_id (MetaOutput *outputs,
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].winsys_id == id)
if (outputs[i].output_id == id)
return &outputs[i];
return NULL;
@@ -361,9 +363,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
@@ -406,7 +408,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
meta_output->winsys_id = connector->connector_id;
meta_output->output_id = connector->connector_id;
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
@@ -489,7 +491,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->winsys_id);
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
@@ -665,7 +667,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
@@ -746,7 +748,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->winsys_id;
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;

View File

@@ -151,15 +151,10 @@ handle_host_xevent (MetaBackend *backend,
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
gboolean bypass_clutter = FALSE;
XGetEventData (priv->xdisplay, &event->xcookie);
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
bypass_clutter = TRUE;
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
@@ -257,24 +252,6 @@ x_event_source_new (MetaBackend *backend)
return source;
}
static void
take_touch_grab (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
DefaultRootWindow (priv->xdisplay),
False, &mask, 1, &mods);
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
@@ -312,8 +289,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
take_touch_grab (backend);
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}

View File

@@ -42,7 +42,7 @@
#include "edid.h"
#include "meta-monitor-config.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
/* Look for DPI_FALLBACK in:
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
@@ -67,31 +67,31 @@ struct _MetaMonitorManagerXrandrClass
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
static MetaMonitorTransform
meta_monitor_transform_from_xrandr (Rotation rotation)
static enum wl_output_transform
wl_transform_from_xrandr (Rotation rotation)
{
static const MetaMonitorTransform y_reflected_map[4] = {
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_270
static const enum wl_output_transform y_reflected_map[4] = {
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
MetaMonitorTransform ret;
enum wl_output_transform ret;
switch (rotation & 0x7F)
{
default:
case RR_Rotate_0:
ret = META_MONITOR_TRANSFORM_NORMAL;
ret = WL_OUTPUT_TRANSFORM_NORMAL;
break;
case RR_Rotate_90:
ret = META_MONITOR_TRANSFORM_90;
ret = WL_OUTPUT_TRANSFORM_90;
break;
case RR_Rotate_180:
ret = META_MONITOR_TRANSFORM_180;
ret = WL_OUTPUT_TRANSFORM_180;
break;
case RR_Rotate_270:
ret = META_MONITOR_TRANSFORM_270;
ret = WL_OUTPUT_TRANSFORM_270;
break;
}
@@ -105,35 +105,35 @@ meta_monitor_transform_from_xrandr (Rotation rotation)
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
static MetaMonitorTransform
meta_monitor_transform_from_xrandr_all (Rotation rotation)
static unsigned int
wl_transform_from_xrandr_all (Rotation rotation)
{
unsigned ret;
/* Handle the common cases first (none or all) */
if (rotation == 0 || rotation == RR_Rotate_0)
return (1 << META_MONITOR_TRANSFORM_NORMAL);
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
/* All rotations and one reflection -> all of them by composition */
if ((rotation & ALL_ROTATIONS) &&
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
return ALL_TRANSFORMS;
return ALL_WL_TRANSFORMS;
ret = 1 << META_MONITOR_TRANSFORM_NORMAL;
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (rotation & RR_Rotate_90)
ret |= 1 << META_MONITOR_TRANSFORM_90;
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
if (rotation & RR_Rotate_180)
ret |= 1 << META_MONITOR_TRANSFORM_180;
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
if (rotation & RR_Rotate_270)
ret |= 1 << META_MONITOR_TRANSFORM_270;
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
return ret;
}
@@ -150,7 +150,7 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_CARDINAL,
&actual_type, &actual_format,
@@ -186,7 +186,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
@@ -211,7 +211,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom);
if (info == NULL)
@@ -278,25 +278,25 @@ get_edid_property (Display *dpy,
static GBytes *
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
XID winsys_id)
XID output_id)
{
Atom edid_atom;
guint8 *result;
gsize len;
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (result)
@@ -312,14 +312,14 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID winsys_id)
XID output_id)
{
Atom atom;
XRRPropertyInfo *info;
gboolean result = FALSE;
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, winsys_id,
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
atom);
if (info)
@@ -434,8 +434,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations);
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
for (j = 0; j < (unsigned)resources->nmode; j++)
{
@@ -467,10 +467,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
GBytes *edid;
MonitorInfo *parsed_edid;
meta_output->winsys_id = resources->outputs[i];
meta_output->output_id = resources->outputs[i];
meta_output->name = g_strdup (output->name);
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
edid = read_output_edid (manager_xrandr, meta_output->output_id);
if (edid)
{
gsize len;
@@ -504,7 +504,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->winsys_id);
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@@ -556,7 +556,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
}
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
@@ -589,7 +589,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
for (k = 0; k < manager->n_outputs; k++)
{
if (clone == (XID)manager->outputs[k].winsys_id)
if (clone == (XID)manager->outputs[k].output_id)
{
meta_output->possible_clones[j] = &manager->outputs[k];
break;
@@ -605,7 +605,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
return read_output_edid (manager_xrandr, output->winsys_id);
return read_output_edid (manager_xrandr, output->output_id);
}
static void
@@ -637,25 +637,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
}
static Rotation
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
wl_transform_to_xrandr (enum wl_output_transform transform)
{
switch (transform)
{
case META_MONITOR_TRANSFORM_NORMAL:
case WL_OUTPUT_TRANSFORM_NORMAL:
return RR_Rotate_0;
case META_MONITOR_TRANSFORM_90:
case WL_OUTPUT_TRANSFORM_90:
return RR_Rotate_90;
case META_MONITOR_TRANSFORM_180:
case WL_OUTPUT_TRANSFORM_180:
return RR_Rotate_180;
case META_MONITOR_TRANSFORM_270:
case WL_OUTPUT_TRANSFORM_270:
return RR_Rotate_270;
case META_MONITOR_TRANSFORM_FLIPPED:
case WL_OUTPUT_TRANSFORM_FLIPPED:
return RR_Reflect_X | RR_Rotate_0;
case META_MONITOR_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return RR_Reflect_X | RR_Rotate_90;
case META_MONITOR_TRANSFORM_FLIPPED_180:
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return RR_Reflect_X | RR_Rotate_180;
case META_MONITOR_TRANSFORM_FLIPPED_270:
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return RR_Reflect_X | RR_Rotate_270;
}
@@ -672,7 +672,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1);
@@ -828,7 +828,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->crtc = crtc;
new_controlled_mask |= 1UL << j;
outputs[j] = output->winsys_id;
outputs[j] = output->output_id;
}
if (crtc->current_mode == mode &&
@@ -847,7 +847,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
manager_xrandr->time,
crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
meta_monitor_transform_to_xrandr (crtc_info->transform),
wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
if (ok != Success)
@@ -891,7 +891,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
{
XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->winsys_id);
(XID)output_info->output->output_id);
}
output_set_presentation_xrandr (manager_xrandr,
@@ -934,7 +934,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1);

View File

@@ -148,6 +148,33 @@ process_damage (MetaCompositor *compositor,
meta_window_actor_process_x11_damage (window_actor, event);
}
static Window
get_output_window (MetaCompositor *compositor)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
Window output;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
meta_core_add_old_event_mask (xdisplay, output, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, output, &mask, 1);
return output;
}
/* compat helper */
static MetaCompositor *
get_compositor_for_screen (MetaScreen *screen)
@@ -467,12 +494,12 @@ meta_compositor_manage (MetaCompositor *compositor)
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
compositor->stage = meta_stage_new ();
clutter_actor_show (compositor->stage);
wayland_compositor->stage = compositor->stage;
meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (compositor->stage, width, height);
clutter_actor_show (compositor->stage);
}
else
{
@@ -491,6 +518,8 @@ meta_compositor_manage (MetaCompositor *compositor)
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
@@ -507,16 +536,10 @@ meta_compositor_manage (MetaCompositor *compositor)
}
}
/* We use connect_after() here to accomodate code in GNOME Shell that,
* when benchmarking drawing performance, connects to ::after-paint
* and calls glFinish(). The timing information from that will be
* more accurate if we hold off until that completes before we signal
* apps to begin drawing the next frame. If there are no other
* connections to ::after-paint, connect() vs. connect_after() doesn't
* matter.
*/
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
G_CALLBACK (after_stage_paint), compositor);
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
after_stage_paint,
compositor,
NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
@@ -535,8 +558,7 @@ meta_compositor_manage (MetaCompositor *compositor)
}
else
{
compositor->output = screen->composite_overlay_window;
compositor->output = get_output_window (compositor);
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
meta_empty_stage_input_region (screen);
@@ -741,6 +763,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
return TRUE;
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{

View File

@@ -109,7 +109,7 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
}
static int
get_output_scale (int winsys_id)
get_output_scale (int output_id)
{
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
MetaOutput *outputs;
@@ -120,7 +120,7 @@ get_output_scale (int winsys_id)
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == winsys_id)
if (outputs[i].output_id == output_id)
{
output_scale = outputs[i].scale;
break;
@@ -150,7 +150,7 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
output_scale = get_output_scale (window->monitor->winsys_id);
output_scale = get_output_scale (window->monitor->output_id);
return (double)output_scale / (double)priv->surface->scale;
}

View File

@@ -36,12 +36,6 @@
#include "wayland/meta-wayland-surface.h"
typedef enum {
INITIALLY_FROZEN,
DRAWING_FIRST_FRAME,
EMITTED_FIRST_FRAME
} FirstFrameState;
struct _MetaWindowActorPrivate
{
MetaWindow *window;
@@ -110,7 +104,6 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1;
guint updates_frozen : 1;
guint first_frame_state : 2; /* FirstFrameState */
};
typedef struct _FrameData FrameData;
@@ -122,14 +115,6 @@ struct _FrameData
gint64 frame_drawn_time;
};
enum
{
FIRST_FRAME,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
enum
{
PROP_META_WINDOW = 1,
@@ -196,31 +181,6 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
actor_class->paint = meta_window_actor_paint;
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
/**
* MetaWindowActor::first-frame:
* @actor: the #MetaWindowActor instance
*
* The ::first-frame signal will be emitted the first time a frame
* of window contents has been drawn by the application and Mutter
* has had the chance to drawn that frame to the screen. If the
* window starts off initially hidden, obscured, or on on a
* different workspace, the ::first-frame signal will be emitted
* even though the user doesn't see the contents.
*
* MetaDisplay::window-created is a good place to connect to this
* signal - at that point, the MetaWindowActor for the window
* exists, but the window has reliably not yet been drawn.
* Connecting to an existing window that has already been drawn to
* the screen is not useful.
*/
signals[FIRST_FRAME] =
g_signal_new ("first-frame",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
pspec = g_param_spec_object ("meta-window",
"MetaWindow",
"The displayed MetaWindow",
@@ -346,9 +306,6 @@ meta_window_actor_thaw (MetaWindowActor *self)
if (priv->freeze_count > 0)
return;
if (priv->first_frame_state == INITIALLY_FROZEN)
priv->first_frame_state = DRAWING_FIRST_FRAME;
if (priv->surface)
meta_surface_actor_set_frozen (priv->surface, FALSE);
@@ -391,9 +348,6 @@ set_surface (MetaWindowActor *self,
* frozen as well... */
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN)
priv->first_frame_state = DRAWING_FIRST_FRAME;
meta_window_actor_update_shape (self);
}
}
@@ -899,7 +853,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc)
if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc)
{
refresh_rate = outputs[i].crtc->current_mode->refresh_rate;
break;
@@ -1374,11 +1328,6 @@ meta_window_actor_new (MetaWindow *window)
meta_window_actor_sync_updates_frozen (self);
if (is_frozen (self))
priv->first_frame_state = INITIALLY_FROZEN;
else
priv->first_frame_state = DRAWING_FIRST_FRAME;
/* If a window doesn't start off with updates frozen, we should
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
*/
@@ -1961,12 +1910,6 @@ meta_window_actor_post_paint (MetaWindowActor *self)
do_send_frame_drawn (self, priv->frames->data);
priv->needs_frame_drawn = FALSE;
}
if (priv->first_frame_state == DRAWING_FIRST_FRAME)
{
priv->first_frame_state = EMITTED_FIRST_FRAME;
g_signal_emit (self, signals[FIRST_FRAME], 0);
}
}
static void

View File

@@ -495,5 +495,46 @@ meta_core_set_screen_cursor (Display *xdisplay,
void
meta_invalidate_default_icons (void)
{
/* XXX: Actually invalidate the icons when they're used. */
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,
XIEventMask *mask)
{
XIEventMask *prev;
gint n_masks, i, j;
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
for (i = 0; i < n_masks; i++)
{
if (prev[i].deviceid != XIAllMasterDevices)
continue;
for (j = 0; j < MIN (mask->mask_len, prev[i].mask_len); j++)
mask->mask[j] |= prev[i].mask[j];
}
XFree (prev);
}

View File

@@ -169,4 +169,8 @@ void meta_core_set_screen_cursor (Display *xdisplay,
void meta_invalidate_default_icons (void);
void meta_core_add_old_event_mask (Display *xdisplay,
Window xwindow,
XIEventMask *mask);
#endif

View File

@@ -37,6 +37,8 @@
#include <stdlib.h>
#include <stdio.h>
#include "wayland/meta-wayland-surface.h"
static void
dialog_exited (GPid pid, int status, gpointer user_data)
{

View File

@@ -35,7 +35,7 @@
#include <meta/boxes.h>
#include <meta/display.h>
#include "keybindings-private.h"
#include "meta-gesture-tracker-private.h"
#include "gesture-tracker-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
@@ -146,6 +146,8 @@ struct _MetaDisplay
GHashTable *xids;
GHashTable *wayland_windows;
int server_grab_count;
/* serials of leave/unmap events that may
* correspond to an enter event we should
* ignore
@@ -312,6 +314,8 @@ struct _MetaDisplayClass
gboolean meta_display_open (void);
void meta_display_close (MetaDisplay *display,
guint32 timestamp);
void meta_display_grab (MetaDisplay *display);
void meta_display_ungrab (MetaDisplay *display);
void meta_display_unmanage_windows_for_screen (MetaDisplay *display,
MetaScreen *screen,
@@ -441,16 +445,6 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
guint32 *timestamp);
void meta_display_remove_pending_pings_for_window (MetaDisplay *display,
MetaWindow *window);
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
gboolean meta_display_show_restart_message (MetaDisplay *display,
const char *message);
gboolean meta_display_request_restart (MetaDisplay *display);
void meta_restart_init (void);
void meta_restart_finish (void);
#endif

View File

@@ -52,6 +52,7 @@
#include "meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#include "compositor-private.h"
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
@@ -71,6 +72,7 @@
#include "x11/xprops.h"
#include "wayland/meta-xwayland-private.h"
#include "meta-surface-actor-wayland.h"
/*
* SECTION:pings
@@ -117,8 +119,6 @@ enum
WINDOW_MARKED_URGENT,
GRAB_OP_BEGIN,
GRAB_OP_END,
SHOW_RESTART_MESSAGE,
RESTART,
LAST_SIGNAL
};
@@ -148,6 +148,11 @@ static void update_window_grab_modifiers (MetaDisplay *display);
static void prefs_changed_callback (MetaPreference pref,
void *data);
static void meta_display_grab_window_touch (MetaDisplay *display,
Window xwindow);
static void meta_display_ungrab_window_touch (MetaDisplay *display,
Window xwindow);
static void
meta_display_get_property(GObject *object,
guint prop_id,
@@ -271,59 +276,6 @@ meta_display_class_init (MetaDisplayClass *klass)
META_TYPE_WINDOW,
META_TYPE_GRAB_OP);
/**
* MetaDisplay::show-restart-message:
* @display: the #MetaDisplay instance
* @message: (allow-none): The message to display, or %NULL
* to clear a previous restart message.
*
* The ::show-restart-message signal will be emitted to indicate
* that the compositor should show a message during restart. This is
* emitted when meta_restart() is called, either by Mutter
* internally or by the embedding compositor. The message should be
* immediately added to the Clutter stage in its final form -
* ::restart will be emitted to exit the application and leave the
* stage contents frozen as soon as the the stage is painted again.
*
* On case of failure to restart, this signal will be emitted again
* with %NULL for @message.
*
* Returns: %TRUE means the message was added to the stage; %FALSE
* indicates that the compositor did not show the message.
*/
display_signals[SHOW_RESTART_MESSAGE] =
g_signal_new ("show-restart-message",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled,
NULL, NULL,
G_TYPE_BOOLEAN, 1,
G_TYPE_STRING);
/**
* MetaDisplay::restart:
* @display: the #MetaDisplay instance
*
* The ::restart signal is emitted to indicate that compositor
* should reexec the process. This is
* emitted when meta_restart() is called, either by Mutter
* internally or by the embedding compositor. See also
* ::show-restart-message.
*
* Returns: %FALSE to indicate that the compositor could not
* be restarted. When the compositor is restarted, the signal
* should not return.
*/
display_signals[RESTART] =
g_signal_new ("restart",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled,
NULL, NULL,
G_TYPE_BOOLEAN, 0);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
g_param_spec_object ("focus-window",
@@ -350,9 +302,16 @@ ping_data_free (MetaPingData *ping_data)
g_free (ping_data);
}
void
meta_display_remove_pending_pings_for_window (MetaDisplay *display,
MetaWindow *window)
/**
* remove_pending_pings_for_window:
* @display: The display the window appears on
* @xwindow: The X ID of the window whose pings we should remove
*
* Frees every pending ping structure for the given X window on the
* given display. This means that we also destroy the timeouts.
*/
static void
remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
{
GSList *tmp;
GSList *dead;
@@ -365,7 +324,7 @@ meta_display_remove_pending_pings_for_window (MetaDisplay *display,
{
MetaPingData *ping_data = tmp->data;
if (ping_data->window == window)
if (ping_data->window->xwindow == xwindow)
dead = g_slist_prepend (dead, ping_data);
}
@@ -496,7 +455,6 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker,
gboolean
meta_display_open (void)
{
MetaDisplay *display;
Display *xdisplay;
MetaScreen *screen;
int i;
@@ -528,223 +486,224 @@ meta_display_open (void)
XSynchronize (xdisplay, True);
g_assert (the_display == NULL);
display = the_display = g_object_new (META_TYPE_DISPLAY, NULL);
the_display = g_object_new (META_TYPE_DISPLAY, NULL);
display->closing = 0;
the_display->closing = 0;
/* here we use XDisplayName which is what the user
* probably put in, vs. DisplayString(display) which is
* canonicalized by XOpenDisplay()
*/
display->name = g_strdup (XDisplayName (NULL));
display->xdisplay = xdisplay;
display->display_opening = TRUE;
the_display->name = g_strdup (XDisplayName (NULL));
the_display->xdisplay = xdisplay;
the_display->server_grab_count = 0;
the_display->display_opening = TRUE;
display->pending_pings = NULL;
display->autoraise_timeout_id = 0;
display->autoraise_window = NULL;
display->focus_window = NULL;
display->focus_serial = 0;
display->server_focus_window = None;
display->server_focus_serial = 0;
the_display->pending_pings = NULL;
the_display->autoraise_timeout_id = 0;
the_display->autoraise_window = NULL;
the_display->focus_window = NULL;
the_display->focus_serial = 0;
the_display->server_focus_window = None;
the_display->server_focus_serial = 0;
display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
terminal has the focus */
meta_bell_init (display);
meta_bell_init (the_display);
meta_display_init_keys (display);
meta_display_init_keys (the_display);
update_window_grab_modifiers (display);
update_window_grab_modifiers (the_display);
meta_prefs_add_listener (prefs_changed_callback, display);
meta_prefs_add_listener (prefs_changed_callback, the_display);
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
XInternAtoms (the_display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
{
int i = 0;
#define item(x) display->atom_##x = atoms[i++];
#define item(x) the_display->atom_##x = atoms[i++];
#include <meta/atomnames.h>
#undef item
}
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (display);
the_display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (the_display);
the_display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (the_display);
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
*/
display->leader_window = None;
display->timestamp_pinging_window = None;
the_display->leader_window = None;
the_display->timestamp_pinging_window = None;
display->monitor_cache_invalidated = TRUE;
the_display->monitor_cache_invalidated = TRUE;
display->groups_by_leader = NULL;
the_display->groups_by_leader = NULL;
display->screen = NULL;
the_display->screen = NULL;
#ifdef HAVE_STARTUP_NOTIFICATION
display->sn_display = sn_display_new (display->xdisplay,
the_display->sn_display = sn_display_new (the_display->xdisplay,
sn_error_trap_push,
sn_error_trap_pop);
#endif
/* Get events */
meta_display_init_events (display);
meta_display_init_events (the_display);
display->xids = g_hash_table_new (meta_unsigned_long_hash,
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);
display->wayland_windows = g_hash_table_new (NULL, NULL);
the_display->wayland_windows = g_hash_table_new (NULL, NULL);
i = 0;
while (i < N_IGNORED_CROSSING_SERIALS)
{
display->ignored_crossing_serials[i] = 0;
the_display->ignored_crossing_serials[i] = 0;
++i;
}
display->ungrab_should_not_cause_focus_window = None;
the_display->ungrab_should_not_cause_focus_window = None;
display->current_time = CurrentTime;
display->sentinel_counter = 0;
the_display->current_time = CurrentTime;
the_display->sentinel_counter = 0;
display->grab_resize_timeout_id = 0;
display->grab_have_keyboard = FALSE;
the_display->grab_resize_timeout_id = 0;
the_display->grab_have_keyboard = FALSE;
#ifdef HAVE_XKB
display->last_bell_time = 0;
the_display->last_bell_time = 0;
#endif
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
the_display->grab_op = META_GRAB_OP_NONE;
the_display->grab_window = NULL;
the_display->grab_tile_mode = META_TILE_NONE;
the_display->grab_tile_monitor_number = -1;
display->grab_edge_resistance_data = NULL;
the_display->grab_edge_resistance_data = NULL;
{
int major, minor;
display->have_xsync = FALSE;
the_display->have_xsync = FALSE;
display->xsync_error_base = 0;
display->xsync_event_base = 0;
the_display->xsync_error_base = 0;
the_display->xsync_event_base = 0;
/* I don't think we really have to fill these in */
major = SYNC_MAJOR_VERSION;
minor = SYNC_MINOR_VERSION;
if (!XSyncQueryExtension (display->xdisplay,
&display->xsync_event_base,
&display->xsync_error_base) ||
!XSyncInitialize (display->xdisplay,
if (!XSyncQueryExtension (the_display->xdisplay,
&the_display->xsync_event_base,
&the_display->xsync_error_base) ||
!XSyncInitialize (the_display->xdisplay,
&major, &minor))
{
display->xsync_error_base = 0;
display->xsync_event_base = 0;
the_display->xsync_error_base = 0;
the_display->xsync_event_base = 0;
}
else
{
display->have_xsync = TRUE;
XSyncSetPriority (display->xdisplay, None, 10);
the_display->have_xsync = TRUE;
XSyncSetPriority (the_display->xdisplay, None, 10);
}
meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
major, minor,
display->xsync_error_base,
display->xsync_event_base);
the_display->xsync_error_base,
the_display->xsync_event_base);
}
{
display->have_shape = FALSE;
the_display->have_shape = FALSE;
display->shape_error_base = 0;
display->shape_event_base = 0;
the_display->shape_error_base = 0;
the_display->shape_event_base = 0;
if (!XShapeQueryExtension (display->xdisplay,
&display->shape_event_base,
&display->shape_error_base))
if (!XShapeQueryExtension (the_display->xdisplay,
&the_display->shape_event_base,
&the_display->shape_error_base))
{
display->shape_error_base = 0;
display->shape_event_base = 0;
the_display->shape_error_base = 0;
the_display->shape_event_base = 0;
}
else
display->have_shape = TRUE;
the_display->have_shape = TRUE;
meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
display->shape_error_base,
display->shape_event_base);
the_display->shape_error_base,
the_display->shape_event_base);
}
{
display->have_composite = FALSE;
the_display->have_composite = FALSE;
display->composite_error_base = 0;
display->composite_event_base = 0;
the_display->composite_error_base = 0;
the_display->composite_event_base = 0;
if (!XCompositeQueryExtension (display->xdisplay,
&display->composite_event_base,
&display->composite_error_base))
if (!XCompositeQueryExtension (the_display->xdisplay,
&the_display->composite_event_base,
&the_display->composite_error_base))
{
display->composite_error_base = 0;
display->composite_event_base = 0;
the_display->composite_error_base = 0;
the_display->composite_event_base = 0;
}
else
{
display->composite_major_version = 0;
display->composite_minor_version = 0;
if (XCompositeQueryVersion (display->xdisplay,
&display->composite_major_version,
&display->composite_minor_version))
the_display->composite_major_version = 0;
the_display->composite_minor_version = 0;
if (XCompositeQueryVersion (the_display->xdisplay,
&the_display->composite_major_version,
&the_display->composite_minor_version))
{
display->have_composite = TRUE;
the_display->have_composite = TRUE;
}
else
{
display->composite_major_version = 0;
display->composite_minor_version = 0;
the_display->composite_major_version = 0;
the_display->composite_minor_version = 0;
}
}
meta_verbose ("Attempted to init Composite, found error base %d event base %d "
"extn ver %d %d\n",
display->composite_error_base,
display->composite_event_base,
display->composite_major_version,
display->composite_minor_version);
the_display->composite_error_base,
the_display->composite_event_base,
the_display->composite_major_version,
the_display->composite_minor_version);
display->have_damage = FALSE;
the_display->have_damage = FALSE;
display->damage_error_base = 0;
display->damage_event_base = 0;
the_display->damage_error_base = 0;
the_display->damage_event_base = 0;
if (!XDamageQueryExtension (display->xdisplay,
&display->damage_event_base,
&display->damage_error_base))
if (!XDamageQueryExtension (the_display->xdisplay,
&the_display->damage_event_base,
&the_display->damage_error_base))
{
display->damage_error_base = 0;
display->damage_event_base = 0;
the_display->damage_error_base = 0;
the_display->damage_event_base = 0;
}
else
display->have_damage = TRUE;
the_display->have_damage = TRUE;
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
display->damage_error_base,
display->damage_event_base);
the_display->damage_error_base,
the_display->damage_event_base);
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
the_display->xfixes_error_base = 0;
the_display->xfixes_event_base = 0;
if (XFixesQueryExtension (display->xdisplay,
&display->xfixes_event_base,
&display->xfixes_error_base))
if (XFixesQueryExtension (the_display->xdisplay,
&the_display->xfixes_event_base,
&the_display->xfixes_error_base))
{
int xfixes_major, xfixes_minor;
XFixesQueryVersion (display->xdisplay, &xfixes_major, &xfixes_minor);
XFixesQueryVersion (the_display->xdisplay, &xfixes_major, &xfixes_minor);
if (xfixes_major * 100 + xfixes_minor < 500)
meta_fatal ("Mutter requires XFixes 5.0");
@@ -755,21 +714,21 @@ meta_display_open (void)
}
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
display->xfixes_error_base,
display->xfixes_event_base);
the_display->xfixes_error_base,
the_display->xfixes_event_base);
}
{
int major = 2, minor = 3;
gboolean has_xi = FALSE;
if (XQueryExtension (display->xdisplay,
if (XQueryExtension (the_display->xdisplay,
"XInputExtension",
&display->xinput_opcode,
&display->xinput_error_base,
&display->xinput_event_base))
&the_display->xinput_opcode,
&the_display->xinput_error_base,
&the_display->xinput_event_base))
{
if (XIQueryVersion (display->xdisplay, &major, &minor) == Success)
if (XIQueryVersion (the_display->xdisplay, &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version >= 22)
@@ -777,7 +736,7 @@ meta_display_open (void)
#ifdef HAVE_XI23
if (version >= 23)
display->have_xinput_23 = TRUE;
the_display->have_xinput_23 = TRUE;
#endif /* HAVE_XI23 */
}
}
@@ -801,35 +760,35 @@ meta_display_open (void)
* this window, so we can't rely on it still being set later. See bug
* 354213 for details.
*/
display->leader_window =
meta_create_offscreen_window (display->xdisplay,
DefaultRootWindow (display->xdisplay),
the_display->leader_window =
meta_create_offscreen_window (the_display->xdisplay,
DefaultRootWindow (the_display->xdisplay),
PropertyChangeMask);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__NET_WM_NAME,
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__NET_WM_NAME,
net_wm_name);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__GNOME_WM_KEYBINDINGS,
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__GNOME_WM_KEYBINDINGS,
gnome_wm_keybindings);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__MUTTER_VERSION,
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__MUTTER_VERSION,
VERSION);
data[0] = display->leader_window;
XChangeProperty (display->xdisplay,
display->leader_window,
display->atom__NET_SUPPORTING_WM_CHECK,
data[0] = the_display->leader_window;
XChangeProperty (the_display->xdisplay,
the_display->leader_window,
the_display->atom__NET_SUPPORTING_WM_CHECK,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
XWindowEvent (display->xdisplay,
display->leader_window,
XWindowEvent (the_display->xdisplay,
the_display->leader_window,
PropertyChangeMask,
&event);
@@ -838,51 +797,52 @@ meta_display_open (void)
/* Make it painfully clear that we can't rely on PropertyNotify events on
* this window, as per bug 354213.
*/
XSelectInput(display->xdisplay,
display->leader_window,
XSelectInput(the_display->xdisplay,
the_display->leader_window,
NoEventMask);
}
/* Make a little window used only for pinging the server for timestamps; note
* that meta_create_offscreen_window already selects for PropertyChangeMask.
*/
display->timestamp_pinging_window =
meta_create_offscreen_window (display->xdisplay,
DefaultRootWindow (display->xdisplay),
the_display->timestamp_pinging_window =
meta_create_offscreen_window (the_display->xdisplay,
DefaultRootWindow (the_display->xdisplay),
PropertyChangeMask);
display->last_focus_time = timestamp;
display->last_user_time = timestamp;
display->compositor = NULL;
the_display->last_focus_time = timestamp;
the_display->last_user_time = timestamp;
the_display->compositor = NULL;
/* Mutter used to manage all X screens of the display in a single process, but
* now it always manages exactly one screen as specified by the DISPLAY
* environment variable.
*/
i = meta_ui_get_screen_number ();
screen = meta_screen_new (display, i, timestamp);
screen = meta_screen_new (the_display, i, timestamp);
if (!screen)
{
/* This would typically happen because all the screens already
* have window managers.
*/
meta_display_close (display, timestamp);
meta_display_close (the_display, timestamp);
return FALSE;
}
display->screen = screen;
the_display->screen = screen;
enable_compositor (the_display);
meta_screen_init_workspaces (screen);
enable_compositor (display);
meta_screen_create_guard_window (screen);
/* Set up touch support */
display->gesture_tracker = meta_gesture_tracker_new ();
g_signal_connect (display->gesture_tracker, "state-changed",
G_CALLBACK (gesture_tracker_state_changed), display);
the_display->gesture_tracker = meta_gesture_tracker_new (0);
g_signal_connect (the_display->gesture_tracker, "state-changed",
G_CALLBACK (gesture_tracker_state_changed), the_display);
meta_display_grab_window_touch (the_display,
DefaultRootWindow (the_display->xdisplay));
/* We know that if mutter is running as a Wayland compositor,
* we start out with no windows.
@@ -895,12 +855,12 @@ meta_display_open (void)
int ret_to;
/* kinda bogus because GetInputFocus has no possible errors */
meta_error_trap_push (display);
meta_error_trap_push (the_display);
/* FIXME: This is totally broken; see comment 9 of bug 88194 about this */
focus = None;
ret_to = RevertToPointerRoot;
XGetInputFocus (display->xdisplay, &focus, &ret_to);
XGetInputFocus (the_display->xdisplay, &focus, &ret_to);
/* Force a new FocusIn (does this work?) */
@@ -909,29 +869,29 @@ meta_display_open (void)
*/
if (focus == None || focus == PointerRoot)
/* Just focus the no_focus_window on the first screen */
meta_display_focus_the_no_focus_window (display,
display->screen,
meta_display_focus_the_no_focus_window (the_display,
the_display->screen,
timestamp);
else
{
MetaWindow * window;
window = meta_display_lookup_x_window (display, focus);
window = meta_display_lookup_x_window (the_display, focus);
if (window)
meta_display_set_input_focus_window (display, window, FALSE, timestamp);
meta_display_set_input_focus_window (the_display, window, FALSE, timestamp);
else
/* Just focus the no_focus_window on the first screen */
meta_display_focus_the_no_focus_window (display,
display->screen,
meta_display_focus_the_no_focus_window (the_display,
the_display->screen,
timestamp);
}
meta_error_trap_pop (display);
meta_error_trap_pop (the_display);
}
meta_idle_monitor_init_dbus ();
/* Done opening new display */
display->display_opening = FALSE;
the_display->display_opening = FALSE;
return TRUE;
}
@@ -1040,7 +1000,6 @@ meta_display_close (MetaDisplay *display,
guint32 timestamp)
{
g_assert (display != NULL);
g_assert (display == the_display);
if (display->closing != 0)
{
@@ -1054,6 +1013,8 @@ meta_display_close (MetaDisplay *display,
meta_display_remove_autoraise_callback (display);
meta_display_ungrab_window_touch (display,
DefaultRootWindow (display->xdisplay));
g_clear_object (&display->gesture_tracker);
if (display->focus_timeout_id)
@@ -1100,6 +1061,50 @@ meta_display_close (MetaDisplay *display,
meta_quit (META_EXIT_SUCCESS);
}
/* Grab/ungrab routines taken from fvwm.
* Calling this function will cause X to ignore all other clients until
* you ungrab. This may not be quite as bad as it sounds, yet there is
* agreement that avoiding server grabs except when they are clearly needed
* is a good thing.
*
* If you do use such grabs, please clearly explain the necessity for their
* usage in a comment. Try to keep their scope extremely limited. In
* particular, try to avoid emitting any signals or notifications while
* a grab is active (if the signal receiver tries to block on an X request
* from another client at this point, you will have a deadlock).
*/
void
meta_display_grab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
{
XGrabServer (display->xdisplay);
}
display->server_grab_count += 1;
meta_verbose ("Grabbing display, grab count now %d\n",
display->server_grab_count);
}
void
meta_display_ungrab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
meta_bug ("Ungrabbed non-grabbed server\n");
display->server_grab_count -= 1;
if (display->server_grab_count == 0)
{
/* FIXME we want to purge all pending "queued" stuff
* at this point, such as window hide/show
*/
XUngrabServer (display->xdisplay);
XFlush (display->xdisplay);
}
meta_verbose ("Ungrabbing display, grab count now %d\n",
display->server_grab_count);
}
/**
* meta_display_for_x_display:
* @xdisplay: An X display
@@ -1534,7 +1539,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
* we know which is which by making two requests that the server will
* process at the same time.
*/
XGrabServer (display->xdisplay);
meta_display_grab (display);
serial = XNextRequest (display->xdisplay);
@@ -1547,8 +1552,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
display->atom__MUTTER_FOCUS_SET,
XA_STRING, 8, PropModeAppend, NULL, 0);
XUngrabServer (display->xdisplay);
XFlush (display->xdisplay);
meta_display_ungrab (display);
meta_display_update_focus_window (display,
meta_window,
@@ -1588,6 +1592,9 @@ meta_display_unregister_x_window (MetaDisplay *display,
g_return_if_fail (g_hash_table_lookup (display->xids, &xwindow) != NULL);
g_hash_table_remove (display->xids, &xwindow);
/* Remove any pending pings */
remove_pending_pings_for_window (display, xwindow);
}
void
@@ -1863,19 +1870,18 @@ void
meta_display_end_grab_op (MetaDisplay *display,
guint32 timestamp)
{
MetaWindow *grab_window = display->grab_window;
MetaGrabOp grab_op = display->grab_op;
meta_topic (META_DEBUG_WINDOW_OPS,
"Ending grab op %u at time %u\n", grab_op, timestamp);
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
if (display->grab_op == META_GRAB_OP_NONE)
return;
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->screen, grab_window, grab_op);
display->screen, display->grab_window, display->grab_op);
if (meta_grab_op_is_moving_or_resizing (grab_op))
meta_window_grab_op_ended (display->grab_window, display->grab_op);
if (meta_grab_op_is_moving_or_resizing (display->grab_op))
{
/* Clear out the edge cache */
meta_display_cleanup_edges (display);
@@ -1901,7 +1907,7 @@ meta_display_end_grab_op (MetaDisplay *display,
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Ungrabbing all keys timestamp %u\n", timestamp);
meta_window_ungrab_all_keys (grab_window, timestamp);
meta_window_ungrab_all_keys (display->grab_window, timestamp);
}
display->grab_timestamp = 0;
@@ -1918,8 +1924,6 @@ meta_display_end_grab_op (MetaDisplay *display,
display->grab_resize_timeout_id = 0;
}
meta_window_grab_op_ended (grab_window, grab_op);
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
}
@@ -2091,6 +2095,35 @@ meta_display_ungrab_window_buttons (MetaDisplay *display,
}
}
static void
meta_display_grab_window_touch (MetaDisplay *display,
Window xwindow)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
xwindow, False, &mask, 1, &mods);
}
static void
meta_display_ungrab_window_touch (MetaDisplay *display,
Window xwindow)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
XIGrabModifiers mods = { XIAnyModifier, 0 };
XIUngrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID, xwindow, 1, &mods);
}
/* Grab buttons we only grab while unfocused in click-to-focus mode */
#define MAX_FOCUS_BUTTON 4
void
@@ -3194,28 +3227,3 @@ meta_display_get_gesture_tracker (MetaDisplay *display)
{
return display->gesture_tracker;
}
gboolean
meta_display_show_restart_message (MetaDisplay *display,
const char *message)
{
gboolean result = FALSE;
g_signal_emit (display,
display_signals[SHOW_RESTART_MESSAGE], 0,
message, &result);
return result;
}
gboolean
meta_display_request_restart (MetaDisplay *display)
{
gboolean result = FALSE;
g_signal_emit (display,
display_signals[RESTART], 0,
&result);
return result;
}

View File

@@ -23,6 +23,7 @@
#include "config.h"
#include "events.h"
#include "core.h"
#include "display-private.h"
#include "window-private.h"
#include "backends/meta-backend.h"

View File

@@ -26,11 +26,14 @@
#include "bell.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include "backends/x11/meta-backend-x11.h"
#define EVENT_MASK (SubstructureRedirectMask | \
StructureNotifyMask | SubstructureNotifyMask | \
ExposureMask | FocusChangeMask)
ExposureMask | \
ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | PointerMotionHintMask | \
EnterWindowMask | LeaveWindowMask | \
FocusChangeMask)
void
meta_window_ensure_frame (MetaWindow *window)
@@ -160,16 +163,10 @@ meta_window_ensure_frame (MetaWindow *window)
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
{
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
}
}
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);

View File

@@ -1,5 +1,12 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file gesture-tracker-private.h Manages gestures on windows/desktop
*
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
* based on the outcome of those.
*/
/*
* Copyright (C) 2014 Red Hat
*
@@ -61,7 +68,7 @@ struct _MetaGestureTrackerClass
GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
MetaGestureTracker * meta_gesture_tracker_new (void);
MetaGestureTracker * meta_gesture_tracker_new (guint autodeny_timeout);
gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
const ClutterEvent *event);

View File

@@ -19,17 +19,8 @@
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:gesture-tracker
* @Title: MetaGestureTracker
* @Short_Description: Manages gestures on windows/desktop
*
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
* based on the outcome of those.
*/
#include "config.h"
#include "meta-gesture-tracker-private.h"
#include "gesture-tracker-private.h"
#include "meta-surface-actor.h"
#define DISTANCE_THRESHOLD 30
@@ -68,22 +59,18 @@ struct _MetaGestureTrackerPrivate
};
enum {
PROP_0,
PROP_AUTODENY_TIMEOUT,
LAST_PROP,
PROP_AUTODENY_TIMEOUT = 1
};
static GParamSpec *obj_props[LAST_PROP];
enum {
STATE_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0 };
#define DEFAULT_AUTODENY_TIMEOUT 150
static guint signals[N_SIGNALS] = { 0 };
static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
@@ -153,16 +140,14 @@ meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
object_class->set_property = meta_gesture_tracker_set_property;
object_class->get_property = meta_gesture_tracker_get_property;
obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout",
"Auto-deny timeout",
"Auto-deny timeout",
0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT,
G_PARAM_STATIC_STRINGS |
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, obj_props);
g_object_class_install_property (object_class,
PROP_AUTODENY_TIMEOUT,
g_param_spec_uint ("autodeny-timeout",
"Auto-deny timeout",
"Auto-deny timeout",
0, G_MAXUINT, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[STATE_CHANGED] =
g_signal_new ("state-changed",
G_TYPE_FROM_CLASS (klass),
@@ -195,7 +180,8 @@ meta_sequence_info_new (MetaGestureTracker *tracker,
guint ms;
priv = meta_gesture_tracker_get_instance_private (tracker);
ms = priv->autodeny_timeout;
ms = (priv->autodeny_timeout) ?
priv->autodeny_timeout : DEFAULT_AUTODENY_TIMEOUT;
info = g_slice_new0 (MetaSequenceInfo);
info->tracker = tracker;
@@ -351,9 +337,11 @@ meta_gesture_tracker_init (MetaGestureTracker *tracker)
}
MetaGestureTracker *
meta_gesture_tracker_new (void)
meta_gesture_tracker_new (guint autodeny_timeout)
{
return g_object_new (META_TYPE_GESTURE_TRACKER, NULL);
return g_object_new (META_TYPE_GESTURE_TRACKER,
"autodeny-timeout", autodeny_timeout,
NULL);
}
static void

View File

@@ -55,6 +55,7 @@
#include <X11/XKBlib.h>
#endif
#include "wayland/meta-wayland.h"
#include "backends/x11/meta-backend-x11.h"
#include "x11/window-x11.h"
@@ -1194,8 +1195,9 @@ meta_window_change_keygrabs (MetaWindow *window,
void
meta_window_grab_keys (MetaWindow *window)
{
/* Under Wayland, we don't need to grab at all. */
if (meta_is_wayland_compositor ())
MetaBackend *backend = meta_get_backend ();
if (!META_IS_BACKEND_X11 (backend))
return;
if (window->all_keys_grabbed)

View File

@@ -94,6 +94,26 @@ static GMainLoop *meta_main_loop = NULL;
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
/**
* log_handler:
* @log_domain: the domain the error occurred in (we ignore this)
* @log_level: the log level so that we can filter out less
* important messages
* @message: the message to log
* @user_data: arbitrary data (we ignore this)
*
* Prints log messages. If Mutter was compiled with backtrace support,
* also prints a backtrace (see meta_print_backtrace()).
*/
static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
meta_warning ("Log level %d: %s\n", log_level, message);
}
/**
* meta_print_compilation_info:
*
@@ -367,8 +387,6 @@ meta_init (void)
meta_clutter_init ();
}
meta_restart_init ();
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
* for now.
@@ -426,10 +444,24 @@ meta_register_with_session (void)
int
meta_run (void)
{
const gchar *log_domains[] = {
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
"Pango", "GLib-GObject", "GThread"
};
guint i;
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
g_log_set_handler (log_domains[i],
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
log_handler, NULL);
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
meta_ui_set_current_theme (meta_prefs_get_theme ());
/* Try to find some theme that'll work if the theme preference

View File

@@ -309,16 +309,9 @@ accelerator_parse (const gchar *accelerator,
keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
if (keyval == XKB_KEY_NoSymbol)
{
char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
g_free (with_xf86);
if (keyval == XKB_KEY_NoSymbol)
{
error = TRUE;
goto out;
}
}
error = TRUE;
goto out;
}
}
accelerator += len;

View File

@@ -1,82 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* SECTION:restart-helper
* @short_description: helper program during a restart
*
* To smoothly restart Mutter, we want to keep the composite
* overlay window enabled during the restart. This is done by
* spawning this program, which keeps a reference to the the composite
* overlay window until Mutter picks it back up.
*/
/*
* Copyright (C) 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
int
main (int argc,
char **argv)
{
Display *display = XOpenDisplay (NULL);
Window selection_window;
XSetWindowAttributes xwa;
unsigned long mask = 0;
xwa.override_redirect = True;
mask |= CWOverrideRedirect;
XCompositeGetOverlayWindow (display, DefaultRootWindow (display));
selection_window = XCreateWindow (display,
DefaultRootWindow (display),
-100, -100, 1, 1, 0,
0,
InputOnly,
DefaultVisual (display, DefaultScreen (display)),
mask, &xwa);
XSetSelectionOwner (display,
XInternAtom (display, "_MUTTER_RESTART_HELPER", False),
selection_window,
CurrentTime);
/* Mutter looks for an (arbitrary) line printed to stdout to know that
* we have started and have a reference to the COW. XSync() so that
* everything is set on the X server before Mutter starts restarting.
*/
XSync (display, False);
printf ("STARTED\n");
fflush (stdout);
while (True)
{
XEvent xev;
XNextEvent (display, &xev);
/* Mutter restarted and unset the selection to indicate that
* it has a reference on the COW again */
if (xev.xany.type == SelectionClear)
return 0;
}
}

View File

@@ -1,212 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* SECTION:restart
* @short_description: Smoothly restart the compositor
*
* There are some cases where we need to restart Mutter in order
* to deal with changes in state - the particular case inspiring
* this is enabling or disabling stereo output. To make this
* fairly smooth for the user, we need to do two things:
*
* - Display a message to the user and make sure that it is
* actually painted before we exit.
* - Use a helper program so that the Composite Overlay Window
* isn't unmapped and mapped.
*
* This handles both of these.
*/
#include <config.h>
#include <clutter/clutter.h>
#include <gio/gunixinputstream.h>
#include <meta/main.h>
#include "ui.h"
#include "util-private.h"
#include "display-private.h"
static gboolean restart_helper_started = FALSE;
static gboolean restart_message_shown = FALSE;
static gboolean is_restart = FALSE;
void
meta_restart_init (void)
{
Display *xdisplay = meta_ui_get_display ();
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
Window restart_helper_window = None;
restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper);
if (restart_helper_window)
is_restart = TRUE;
}
static void
restart_check_ready (void)
{
if (restart_helper_started && restart_message_shown)
meta_display_request_restart (meta_get_display ());
}
static void
restart_helper_read_line_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
gsize length;
char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object),
res,
&length, &error);
if (line == NULL)
{
meta_warning ("Failed to read output from restart helper%s%s\n",
error ? ": " : NULL,
error ? error->message : NULL);
}
else
g_free (line); /* We don't actually care what the restart helper outputs */
g_object_unref (source_object);
restart_helper_started = TRUE;
restart_check_ready ();
}
static gboolean
restart_message_painted (gpointer data)
{
restart_message_shown = TRUE;
restart_check_ready ();
return FALSE;
}
/**
* meta_restart:
* @message: message to display to the user.
*
* Starts the process of restarting the compositor. Note that Mutter's
* involvement here is to make the restart visually smooth for the
* user - it cannot itself safely reexec a program that embeds libmuttter.
* So in order for this to work, the compositor must handle two
* signals - MetaDisplay::show-restart-message, to display the
* message passed here on the Clutter stage, and ::restart to actually
* reexec the compositor.
*/
void
meta_restart (const char *message)
{
MetaDisplay *display = meta_get_display();
GInputStream *unix_stream;
GDataInputStream *data_stream;
GError *error = NULL;
int helper_out_fd;
static const char * const helper_argv[] = {
MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL
};
if (meta_display_show_restart_message (display, message))
{
/* Wait until the stage was painted */
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
restart_message_painted,
NULL, NULL);
}
else
{
/* Can't show the message, show the message as soon as the
* restart helper starts
*/
restart_message_painted (NULL);
}
/* We also need to wait for the restart helper to get its
* reference to the Composite Overlay Window.
*/
if (!g_spawn_async_with_pipes (NULL, /* working directory */
(char **)helper_argv,
NULL, /* envp */
G_SPAWN_DEFAULT,
NULL, NULL, /* child_setup */
NULL, /* child_pid */
NULL, /* standard_input */
&helper_out_fd,
NULL, /* standard_error */
&error))
{
meta_warning ("Failed to start restart helper: %s\n", error->message);
goto error;
}
unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE);
data_stream = g_data_input_stream_new (unix_stream);
g_object_unref (unix_stream);
g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
NULL, restart_helper_read_line_callback,
&error);
if (error != NULL)
{
meta_warning ("Failed to read from restart helper: %s\n", error->message);
g_object_unref (data_stream);
goto error;
}
return;
error:
/* If starting the restart helper fails, then we just go ahead and restart
* immediately. We won't get a smooth transition, since the overlay window
* will be destroyed and recreated, but otherwise it will work fine.
*/
restart_helper_started = TRUE;
restart_check_ready ();
return;
}
void
meta_restart_finish (void)
{
if (is_restart)
{
Display *xdisplay = meta_display_get_xdisplay (meta_get_display ());
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
XSetSelectionOwner (xdisplay, atom_restart_helper, None, CurrentTime);
}
}
/**
* meta_is_restart:
*
* Returns %TRUE if this instance of Mutter comes from Mutter
* restarting itself (for example to enable/disable stereo.)
* See meta_restart(). If this is the case, any startup visuals
* or animations should be suppressed.
*/
gboolean
meta_is_restart (void)
{
return is_restart;
}

View File

@@ -119,8 +119,6 @@ struct _MetaScreen
* and restack them below a guard window. When using a compositor
* this allows us to provide live previews of unmapped windows */
Window guard_window;
Window composite_overlay_window;
};
struct _MetaScreenClass

View File

@@ -45,7 +45,6 @@
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/Xatom.h>
#include <locale.h>
@@ -56,8 +55,6 @@
#include "x11/window-x11.h"
#include "x11/xprops.h"
#include "backends/x11/meta-backend-x11.h"
static char* get_screen_name (MetaDisplay *display,
int number);
@@ -472,24 +469,13 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
XStoreName (xdisplay, guard_window, "mutter guard window");
{
if (!meta_is_wayland_compositor ())
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
/* Sync on the connection we created the window on to
* make sure it's created before we select on it on the
* backend connection. */
XSync (xdisplay, False);
XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
}
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, guard_window, &mask, 1);
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
@@ -506,15 +492,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
return guard_window;
}
/* Set a black background on the root window so that we don't
* see confusing old copies of old windows when debugging
* and testing. */
static void
meta_screen_set_background (MetaScreen *screen)
{
XSetWindowBackground (screen->display->xdisplay, screen->xroot, 0x00000000);
}
MetaScreen*
meta_screen_new (MetaDisplay *display,
int number,
@@ -634,15 +611,24 @@ meta_screen_new (MetaDisplay *display,
/* select our root window events */
meta_error_trap_push (display);
/* We need to or with the existing event mask since
* gtk+ may be interested in other events.
*/
{
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XWindowAttributes attr;
meta_core_add_old_event_mask (xdisplay, xroot, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
#ifdef HAVE_XI23
if (META_DISPLAY_HAS_XINPUT_23 (display))
{
@@ -654,6 +640,9 @@ meta_screen_new (MetaDisplay *display,
event_mask = (SubstructureRedirectMask | SubstructureNotifyMask |
StructureNotifyMask | ColormapChangeMask | PropertyChangeMask);
if (XGetWindowAttributes (xdisplay, xroot, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xroot, event_mask);
}
@@ -667,9 +656,6 @@ meta_screen_new (MetaDisplay *display,
return NULL;
}
/* Select for cursor changes so the cursor tracker is up to date. */
XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask);
screen = g_object_new (META_TYPE_SCREEN, NULL);
screen->closing = 0;
@@ -710,16 +696,9 @@ meta_screen_new (MetaDisplay *display,
screen->starting_corner = META_SCREEN_TOPLEFT;
screen->guard_window = None;
screen->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
/* Now that we've gotten taken a reference count on the COW, we
* can close the helper that is holding on to it */
meta_restart_finish ();
reload_monitor_infos (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
meta_screen_set_background (screen);
/* Handle creating a no_focus_window for this screen */
screen->no_focus_window =
@@ -797,6 +776,7 @@ meta_screen_init_workspaces (MetaScreen *screen)
else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
meta_workspace_activate (screen->workspaces->data, timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
@@ -807,8 +787,6 @@ meta_screen_init_workspaces (MetaScreen *screen)
if (current_workspace != NULL)
meta_workspace_activate (current_workspace, timestamp);
else
meta_workspace_activate (screen->workspaces->data, timestamp);
}
void
@@ -821,6 +799,8 @@ meta_screen_free (MetaScreen *screen,
screen->closing += 1;
meta_display_grab (display);
meta_compositor_unmanage (screen->display->compositor);
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
@@ -877,6 +857,9 @@ meta_screen_free (MetaScreen *screen,
g_free (screen->screen_name);
g_object_unref (screen);
XFlush (display->xdisplay);
meta_display_ungrab (display);
}
void

View File

@@ -234,36 +234,32 @@ meta_stack_op_dump (MetaStackOp *op,
g_free (window_id);
}
static void
stack_dump (GArray *stack)
{
guint i;
meta_push_no_msg_prefix ();
for (i = 0; i < stack->len; i++)
{
MetaStackWindow *window = &g_array_index (stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
}
static void
meta_stack_tracker_dump (MetaStackTracker *tracker)
{
guint i;
GList *l;
meta_topic (META_DEBUG_STACK, "MetaStackTracker state (screen=%d)\n", tracker->screen->number);
meta_push_no_msg_prefix ();
meta_topic (META_DEBUG_STACK, " xserver_serial: %ld\n", tracker->xserver_serial);
meta_topic (META_DEBUG_STACK, " xserver_stack: ");
stack_dump (tracker->xserver_stack);
meta_topic (META_DEBUG_STACK, " verfied_stack: ");
stack_dump (tracker->verified_stack);
meta_topic (META_DEBUG_STACK, " unverified_predictions: [");
for (i = 0; i < tracker->xserver_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n verfied_stack: ");
for (i = 0; i < tracker->verified_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n unverified_predictions: [");
for (l = tracker->unverified_predictions->head; l; l = l->next)
{
MetaStackOp *op = l->data;
@@ -273,8 +269,15 @@ meta_stack_tracker_dump (MetaStackTracker *tracker)
if (tracker->predicted_stack)
{
meta_topic (META_DEBUG_STACK, "\n predicted_stack: ");
stack_dump (tracker->predicted_stack);
for (i = 0; i < tracker->predicted_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->predicted_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
}
@@ -482,12 +485,14 @@ requery_xserver_stack (MetaStackTracker *tracker)
screen->xroot,
&ignored1, &ignored2, &children, &n_children);
tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
tracker->xserver_stack =
g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
g_array_set_size (tracker->xserver_stack, n_children);
for (i = 0; i < n_children; i++)
{
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
MetaStackWindow *window =
&g_array_index (tracker->xserver_stack, MetaStackWindow, i);
window->any.type = META_WINDOW_CLIENT_TYPE_X11;
window->x11.xwindow = children[i];
}
@@ -709,10 +714,14 @@ meta_stack_tracker_record_lower (MetaStackTracker *tracker,
*
* Return value: %TRUE if the predicted state is consistent with
* receiving the given @op from X, else %FALSE.
*
* @modified will be set to %TRUE if tracker->verified_stack is
* changed by applying any newly validated operations, else %FALSE.
*/
static gboolean
stack_tracker_verify_predictions (MetaStackTracker *tracker,
MetaStackOp *op)
MetaStackOp *op,
gboolean *modified)
{
GArray *tmp_predicted_stack = NULL;
GArray *predicted_stack;
@@ -722,8 +731,6 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
* passed to this api. */
g_return_val_if_fail (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_X11, FALSE);
meta_topic (META_DEBUG_STACK, "Verifying predictions:\n");
if (tracker->unverified_predictions->length)
{
GList *l;
@@ -743,9 +750,6 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
else
predicted_stack = tracker->verified_stack;
meta_topic (META_DEBUG_STACK, " predicted_stack: ");
stack_dump (predicted_stack);
switch (op->any.type)
{
case STACK_OP_ADD:
@@ -821,6 +825,7 @@ verified:
meta_stack_op_free (queued_op);
}
*modified = modified_stack;
if (modified_stack)
{
g_array_free (tracker->verified_stack, TRUE);
@@ -842,6 +847,8 @@ not_verified:
tracker->predicted_stack = NULL;
}
*modified = FALSE;
return FALSE;
}
@@ -874,17 +881,17 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
* windows and free the queue of unverified_predictions.
*
* - Iterate through the x windows listed in verified_stack at the
* same time as iterating the windows in xserver_stack. (Stop
* when we reach the end of the xserver_stack)
* same time as iterating the windows in xserver_list. (Stop
* when we reach the end of the xserver_list)
* - If the window found doesn't match the window expected
* according to the order of xserver_stack then:
* according to the order of xserver_list then:
* - Look ahead for the window we were expecting and restack
* that above the previous X window. If we fail to find the
* expected window then create a new entry for it and stack
* that.
*
* - Continue to iterate through verified_stack for any remaining
* X windows that we now know aren't in the xserver_stack and
* X windows that we now know aren't in the xserver_list and
* remove them.
*
* - Free ->predicted_stack if any.
@@ -902,11 +909,15 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
g_queue_clear (tracker->unverified_predictions);
j = 0;
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
expected_xwindow =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
for (i = 0; i < tracker->verified_stack->len; )
for (i = 0;
i < tracker->verified_stack->len;
)
{
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
MetaStackWindow *current =
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
if (current->any.type != META_WINDOW_CLIENT_TYPE_X11)
{
@@ -943,7 +954,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
/* Technically we only need to look forward from i if we
* wanted to optimize this a bit... */
expected_index = find_window (tracker->verified_stack, expected_xwindow);
expected_index =
find_window (tracker->verified_stack, expected_xwindow);
if (expected_index >= 0)
{
@@ -981,7 +993,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
i++;
j++;
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
expected_xwindow =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
if (j >= tracker->xserver_stack->len)
break;
@@ -991,7 +1004,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
* xserver_stack and so we can remove them. */
while (i < tracker->verified_stack->len)
{
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
MetaStackWindow *current =
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
if (current->any.type == META_WINDOW_CLIENT_TYPE_X11)
g_array_remove_index (tracker->verified_stack, i);
@@ -1002,10 +1016,11 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
}
/* If we get to the end of verified_list and there are any remaining
* entries in xserver_stack then append them all to the end */
* entries in xserver_list then append them all to the end */
for (; j < tracker->xserver_stack->len; j++)
{
MetaStackWindow *current = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
MetaStackWindow *current =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
g_array_append_val (tracker->verified_stack, *current);
modified_stack = TRUE;
@@ -1029,13 +1044,19 @@ static void
stack_tracker_event_received (MetaStackTracker *tracker,
MetaStackOp *op)
{
/* If the event is older than our latest requery, then it's
* already included in our tree. Just ignore it. */
if (op->any.serial < tracker->xserver_serial)
return;
gboolean need_sync = FALSE;
gboolean verified;
meta_stack_op_dump (op, "Stack op event received: ", "\n");
if (op->any.serial < tracker->xserver_serial)
{
/* 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;
}
tracker->xserver_serial = op->any.serial;
/* XXX: With the design we have ended up with it looks like we've
@@ -1049,8 +1070,13 @@ stack_tracker_event_received (MetaStackTracker *tracker,
*/
meta_stack_op_apply (op, tracker->xserver_stack);
if (!stack_tracker_verify_predictions (tracker, op))
resync_verified_stack_with_xserver_stack (tracker);
verified = stack_tracker_verify_predictions (tracker, op, &need_sync);
if (!verified)
{
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;
}
meta_stack_tracker_dump (tracker);
}

View File

@@ -43,6 +43,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#include "x11/iconcache.h"
#include "x11/group-private.h"
#include "wayland/meta-wayland-types.h"
@@ -106,6 +107,9 @@ struct _MetaWindow
GdkPixbuf *icon;
GdkPixbuf *mini_icon;
MetaIconCache icon_cache;
Pixmap wm_hints_pixmap;
Pixmap wm_hints_mask;
MetaWindowType type;
@@ -162,7 +166,7 @@ struct _MetaWindow
* that to toggle between normal/tiled or maximized/tiled states. */
guint saved_maximize : 1;
int tile_monitor_number;
int preferred_output_winsys_id;
int preferred_output_id;
/* Whether we're shaded */
guint shaded : 1;
@@ -347,6 +351,10 @@ struct _MetaWindow
/* whether or not the window is from a program running on another machine */
guint is_remote : 1;
/* Used for Wayland -- surfaces can behave as if they were unmapped if
* they have a NULL buffer attached... */
guint surface_mapped;
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
@@ -480,9 +488,6 @@ struct _MetaWindowClass
void (*get_default_skip_hints) (MetaWindow *window,
gboolean *skip_taskbar_out,
gboolean *skip_pager_out);
gboolean (*update_icon) (MetaWindow *window,
GdkPixbuf **icon,
GdkPixbuf **mini_icon);
};
/* These differ from window->has_foo_func in that they consider
@@ -627,6 +632,8 @@ void meta_window_stack_just_below (MetaWindow *window,
void meta_window_set_user_time (MetaWindow *window,
guint32 timestamp);
void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
@@ -668,6 +675,9 @@ void meta_window_handle_leave (MetaWindow *window);
gboolean meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event);
void meta_window_set_surface_mapped (MetaWindow *window,
gboolean surface_mapped);
void meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect);
void meta_window_get_titlebar_rect (MetaWindow *window,
@@ -678,6 +688,8 @@ void meta_window_activate_full (MetaWindow *window,
MetaClientType source_indication,
MetaWorkspace *workspace);
gboolean meta_window_is_client_decorated (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window,
gboolean user_op);

File diff suppressed because it is too large Load Diff

View File

@@ -34,9 +34,6 @@ gboolean meta_get_replace_current_wm (void); /* Actually defined in util
void meta_set_wm_name (const char *wm_name);
void meta_set_gnome_wm_keybindings (const char *wm_keybindings);
void meta_restart (const char *message);
gboolean meta_is_restart (void);
/**
* MetaExitCode:
* @META_EXIT_SUCCESS: Success

View File

@@ -256,7 +256,6 @@ gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
gboolean meta_window_is_above (MetaWindow *window);
gboolean meta_window_allows_move (MetaWindow *window);
gboolean meta_window_allows_resize (MetaWindow *window);
gboolean meta_window_is_client_decorated (MetaWindow *window);
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
void meta_window_shove_titlebar_onscreen (MetaWindow *window);

View File

@@ -1579,6 +1579,7 @@ meta_frames_motion_notify_event (GtkWidget *widget,
MetaUIFrame *frame;
MetaFrames *frames;
MetaFrameControl control;
int x, y;
frames = META_FRAMES (widget);
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
@@ -1587,7 +1588,9 @@ meta_frames_motion_notify_event (GtkWidget *widget,
frames->last_motion_frame = frame;
control = get_control (frames, frame, event->x, event->y);
gdk_window_get_device_position (frame->window, event->device,
&x, &y, NULL);
control = get_control (frames, frame, x, y);
if (frame->button_state == META_BUTTON_STATE_PRESSED)
{

View File

@@ -65,7 +65,7 @@ free_buffer (guchar *pixels, gpointer data)
}
static GdkPixbuf*
blank_pixbuf (int width, int height)
blank_pixbuf (int width, int height, gboolean no_padding)
{
guchar *buf;
int rowstride;
@@ -73,15 +73,18 @@ blank_pixbuf (int width, int height)
g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
/* Always align rows to 32-bit boundaries */
rowstride = 4 * ((4 * width + 4) / 4);
if (no_padding)
rowstride = width * 3;
else
/* Always align rows to 32-bit boundaries */
rowstride = 4 * ((3 * width + 3) / 4);
buf = g_try_malloc (height * rowstride);
if (!buf)
return NULL;
return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB,
TRUE, 8,
FALSE, 8,
width, height, rowstride,
free_buffer, NULL);
}
@@ -193,14 +196,14 @@ meta_gradient_create_interwoven (int width,
{
int i, j, k, l, ll;
long r1, g1, b1, a1, dr1, dg1, db1, da1;
long r2, g2, b2, a2, dr2, dg2, db2, da2;
long r1, g1, b1, dr1, dg1, db1;
long r2, g2, b2, dr2, dg2, db2;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
int rowstride;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -210,22 +213,18 @@ meta_gradient_create_interwoven (int width,
r1 = (long)(colors1[0].red*0xffffff);
g1 = (long)(colors1[0].green*0xffffff);
b1 = (long)(colors1[0].blue*0xffffff);
a1 = (long)(colors1[0].alpha*0xffffff);
r2 = (long)(colors2[0].red*0xffffff);
g2 = (long)(colors2[0].green*0xffffff);
b2 = (long)(colors2[0].blue*0xffffff);
a2 = (long)(colors2[0].alpha*0xffffff);
dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
da1 = ((colors1[1].alpha-colors1[0].alpha)*0xffffff)/(int)height;
dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
da2 = ((colors2[1].alpha-colors2[0].alpha)*0xffffff)/(int)height;
for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
{
@@ -236,19 +235,17 @@ meta_gradient_create_interwoven (int width,
ptr[0] = (unsigned char) (r1>>16);
ptr[1] = (unsigned char) (g1>>16);
ptr[2] = (unsigned char) (b1>>16);
ptr[3] = (unsigned char) (a1>>16);
}
else
{
ptr[0] = (unsigned char) (r2>>16);
ptr[1] = (unsigned char) (g2>>16);
ptr[2] = (unsigned char) (b2>>16);
ptr[3] = (unsigned char) (a2>>16);
}
for (j=1; j <= width/2; j *= 2)
memcpy (&(ptr[j*4]), ptr, j*4);
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
memcpy (&(ptr[j*3]), ptr, j*3);
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
if (++l == ll)
{
@@ -267,12 +264,10 @@ meta_gradient_create_interwoven (int width,
r1+=dr1;
g1+=dg1;
b1+=db1;
a1+=da1;
r2+=dr2;
g2+=dg2;
b2+=db2;
a2+=da2;
}
return pixbuf;
@@ -297,15 +292,15 @@ meta_gradient_create_horizontal (int width, int height,
const GdkRGBA *to)
{
int i;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
int r0, g0, b0, a0;
int rf, gf, bf, af;
int r0, g0, b0;
int rf, gf, bf;
int rowstride;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -316,32 +311,26 @@ meta_gradient_create_horizontal (int width, int height,
r0 = (guchar) (from->red * 0xff);
g0 = (guchar) (from->green * 0xff);
b0 = (guchar) (from->blue * 0xff);
a0 = (guchar) (from->alpha * 0xff);
rf = (guchar) (to->red * 0xff);
gf = (guchar) (to->green * 0xff);
bf = (guchar) (to->blue * 0xff);
af = (guchar) (to->alpha * 0xff);
r = r0 << 16;
g = g0 << 16;
b = b0 << 16;
a = a0 << 16;
dr = ((rf-r0)<<16)/(int)width;
dg = ((gf-g0)<<16)/(int)width;
db = ((bf-b0)<<16)/(int)width;
da = ((af-a0)<<16)/(int)width;
/* render the first line */
for (i=0; i<width; i++)
{
*(ptr++) = (unsigned char)(r>>16);
*(ptr++) = (unsigned char)(g>>16);
*(ptr++) = (unsigned char)(b>>16);
*(ptr++) = (unsigned char)(a>>16);
r += dr;
g += dg;
b += db;
a += da;
}
/* copy the first line to the other lines */
@@ -371,15 +360,15 @@ meta_gradient_create_vertical (int width, int height,
const GdkRGBA *to)
{
int i, j;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
int r0, g0, b0, a0;
int rf, gf, bf, af;
int r0, g0, b0;
int rf, gf, bf;
int rowstride;
unsigned char *pixels;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -389,21 +378,17 @@ meta_gradient_create_vertical (int width, int height,
r0 = (guchar) (from->red * 0xff);
g0 = (guchar) (from->green * 0xff);
b0 = (guchar) (from->blue * 0xff);
a0 = (guchar) (from->alpha * 0xff);
rf = (guchar) (to->red * 0xff);
gf = (guchar) (to->green * 0xff);
bf = (guchar) (to->blue * 0xff);
af = (guchar) (to->alpha * 0xff);
r = r0<<16;
g = g0<<16;
b = b0<<16;
a = a0<<16;
dr = ((rf-r0)<<16)/(int)height;
dg = ((gf-g0)<<16)/(int)height;
db = ((bf-b0)<<16)/(int)height;
da = ((af-a0)<<16)/(int)height;
for (i=0; i<height; i++)
{
@@ -412,16 +397,14 @@ meta_gradient_create_vertical (int width, int height,
ptr[0] = (unsigned char)(r>>16);
ptr[1] = (unsigned char)(g>>16);
ptr[2] = (unsigned char)(b>>16);
ptr[3] = (unsigned char)(a>>16);
for (j=1; j <= width/2; j *= 2)
memcpy (&(ptr[j*4]), ptr, j*4);
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
memcpy (&(ptr[j*3]), ptr, j*3);
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
r+=dr;
g+=dg;
b+=db;
a+=da;
}
return pixbuf;
}
@@ -459,7 +442,7 @@ meta_gradient_create_diagonal (int width, int height,
else if (height == 1)
return meta_gradient_create_horizontal (width, height, from, to);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -476,12 +459,12 @@ meta_gradient_create_diagonal (int width, int height,
ptr = gdk_pixbuf_get_pixels (tmp);
a = ((float)(width - 1))/((float)(height - 1));
width = width * 4;
width = width * 3;
/* copy the first line to the other lines with corresponding offset */
for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
{
memcpy (&(pixels[j]), &ptr[4*(int)offset], width);
memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
offset += a;
}
@@ -496,7 +479,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
int count)
{
int i, j, k;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
@@ -505,7 +488,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
g_return_val_if_fail (count > 2, NULL);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -526,7 +509,6 @@ meta_gradient_create_multi_horizontal (int width, int height,
r = (long)(colors[0].red * 0xffffff);
g = (long)(colors[0].green * 0xffffff);
b = (long)(colors[0].blue * 0xffffff);
a = (long)(colors[0].alpha * 0xffffff);
/* render the first line */
for (i=1; i<count; i++)
@@ -534,30 +516,25 @@ meta_gradient_create_multi_horizontal (int width, int height,
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)width2;
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)width2;
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)width2;
for (j=0; j<width2; j++)
{
*ptr++ = (unsigned char)(r>>16);
*ptr++ = (unsigned char)(g>>16);
*ptr++ = (unsigned char)(b>>16);
*ptr++ = (unsigned char)(a>>16);
r += dr;
g += dg;
b += db;
a += da;
k++;
}
r = (long)(colors[i].red * 0xffffff);
g = (long)(colors[i].green * 0xffffff);
b = (long)(colors[i].blue * 0xffffff);
a = (long)(colors[i].alpha * 0xffffff);
}
for (j=k; j<width; j++)
{
*ptr++ = (unsigned char)(r>>16);
*ptr++ = (unsigned char)(g>>16);
*ptr++ = (unsigned char)(b>>16);
*ptr++ = (unsigned char)(a>>16);
}
/* copy the first line to the other lines */
@@ -574,7 +551,7 @@ meta_gradient_create_multi_vertical (int width, int height,
int count)
{
int i, j, k;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr, *tmp, *pixels;
int height2;
@@ -583,7 +560,7 @@ meta_gradient_create_multi_vertical (int width, int height,
g_return_val_if_fail (count > 2, NULL);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -604,38 +581,33 @@ meta_gradient_create_multi_vertical (int width, int height,
r = (long)(colors[0].red * 0xffffff);
g = (long)(colors[0].green * 0xffffff);
b = (long)(colors[0].blue * 0xffffff);
a = (long)(colors[0].alpha * 0xffffff);
for (i=1; i<count; i++)
{
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)height2;
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)height2;
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)height2;
for (j=0; j<height2; j++)
{
ptr[0] = (unsigned char)(r>>16);
ptr[1] = (unsigned char)(g>>16);
ptr[2] = (unsigned char)(b>>16);
ptr[3] = (unsigned char)(a>>16);
for (x=1; x <= width/2; x *= 2)
memcpy (&(ptr[x*4]), ptr, x*4);
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
memcpy (&(ptr[x*3]), ptr, x*3);
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
ptr += rowstride;
r += dr;
g += dg;
b += db;
a += da;
k++;
}
r = (long)(colors[i].red * 0xffffff);
g = (long)(colors[i].green * 0xffffff);
b = (long)(colors[i].blue * 0xffffff);
a = (long)(colors[i].alpha * 0xffffff);
}
if (k<height)
@@ -645,11 +617,10 @@ meta_gradient_create_multi_vertical (int width, int height,
ptr[0] = (unsigned char) (r>>16);
ptr[1] = (unsigned char) (g>>16);
ptr[2] = (unsigned char) (b>>16);
ptr[3] = (unsigned char) (a>>16);
for (x=1; x <= width/2; x *= 2)
memcpy (&(ptr[x*4]), ptr, x*4);
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
memcpy (&(ptr[x*3]), ptr, x*3);
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
ptr += rowstride;

View File

@@ -163,7 +163,6 @@ color_composite (const GdkRGBA *bg,
color->red = color->red + (fg->red - color->red) * alpha;
color->green = color->green + (fg->green - color->green) * alpha;
color->blue = color->blue + (fg->blue - color->blue) * alpha;
color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
}
/**
@@ -4139,6 +4138,18 @@ meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list,
fill_env (&env, info, rect);
/* FIXME this can be optimized, potentially a lot, by
* compressing multiple ops when possible. For example,
* anything convertible to a pixbuf can be composited
* client-side, and putting a color tint over a pixbuf
* can be done without creating the solid-color pixbuf.
*
* To implement this my plan is to have the idea of a
* compiled draw op (with the string expressions already
* evaluated), we make an array of those, and then fold
* adjacent items when possible.
*/
cairo_save (cr);
for (i = 0; i < op_list->n_ops; i++)
@@ -6343,7 +6354,6 @@ gtk_style_shade (GdkRGBA *a,
b->red = red;
b->green = green;
b->blue = blue;
b->alpha = a->alpha;
}
/**

View File

@@ -26,6 +26,7 @@
#include <meta/util.h>
#include "core.h"
#include "theme-private.h"
#include "x11/events.h"
#include <string.h>
#include <stdlib.h>
@@ -83,31 +84,6 @@ is_input_event (XEvent *event)
event->xcookie.extension == display->xinput_opcode);
}
static gboolean
is_interesting_input_event (XEvent *event)
{
XIEvent *input_event;
if (!is_input_event (event))
return FALSE;
input_event = (XIEvent *) event->xcookie.data;
switch (input_event->evtype)
{
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_Motion:
case XI_Enter:
case XI_Leave:
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
return TRUE;
default:
return FALSE;
}
}
/* We do some of our event handling in frames.c, which expects
* GDK events delivered by GTK+. However, since the transition to
* client side windows, we can't let GDK see button events, since the
@@ -123,7 +99,7 @@ is_interesting_input_event (XEvent *event)
* use more fields, more fields need to be filled out below.
*/
static void
static gboolean
maybe_redirect_mouse_event (XEvent *xevent)
{
GdkDisplay *gdisplay;
@@ -137,6 +113,9 @@ maybe_redirect_mouse_event (XEvent *xevent)
XIDeviceEvent *xev_d = NULL;
XIEnterEvent *xev_e = NULL;
if (!is_input_event (xevent))
return FALSE;
xev = (XIEvent *) xevent->xcookie.data;
switch (xev->evtype)
@@ -153,18 +132,17 @@ maybe_redirect_mouse_event (XEvent *xevent)
window = xev_e->event;
break;
default:
/* Not interested in this event. */
return;
return FALSE;
}
gdisplay = gdk_x11_lookup_xdisplay (xev->display);
ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
if (!ui)
return;
return FALSE;
gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window);
if (gdk_window == NULL)
return;
return FALSE;
gmanager = gdk_display_get_device_manager (gdisplay);
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
@@ -221,13 +199,13 @@ maybe_redirect_mouse_event (XEvent *xevent)
gevent->button.y = xev_d->event_y;
gevent->button.x_root = xev_d->root_x;
gevent->button.y_root = xev_d->root_y;
break;
case XI_Motion:
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
gevent->motion.type = GDK_MOTION_NOTIFY;
gevent->motion.window = g_object_ref (gdk_window);
gevent->motion.time = xev_d->time;
gevent->motion.x = xev_d->event_x;
gevent->motion.y = xev_d->event_y;
gevent->motion.x_root = xev_d->root_x;
gevent->motion.y_root = xev_d->root_y;
@@ -238,7 +216,6 @@ maybe_redirect_mouse_event (XEvent *xevent)
case XI_Leave:
gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
gevent->crossing.window = g_object_ref (gdk_window);
gevent->crossing.time = xev_e->time;
gevent->crossing.x = xev_e->event_x;
gevent->crossing.y = xev_e->event_y;
break;
@@ -251,20 +228,15 @@ maybe_redirect_mouse_event (XEvent *xevent)
gdk_event_set_device (gevent, gdevice);
gtk_main_do_event (gevent);
gdk_event_free (gevent);
return TRUE;
}
static GdkFilterReturn
ui_filter_func (GdkXEvent *xevent,
GdkEvent *event,
static void
ui_filter_func (gpointer xevent,
gpointer data)
{
if (is_interesting_input_event (xevent))
{
maybe_redirect_mouse_event (xevent);
return GDK_FILTER_REMOVE;
}
else
return GDK_FILTER_CONTINUE;
maybe_redirect_mouse_event (xevent);
}
MetaUI*
@@ -290,7 +262,7 @@ meta_ui_new (Display *xdisplay,
*/
gtk_widget_show (GTK_WIDGET (ui->frames));
gdk_window_add_filter (NULL, ui_filter_func, NULL);
meta_display_events_x11_add_func (ui_filter_func, NULL);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
@@ -307,7 +279,7 @@ meta_ui_free (MetaUI *ui)
gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay);
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL);
gdk_window_remove_filter (NULL, ui_filter_func, NULL);
meta_display_events_x11_add_func (ui_filter_func, NULL);
g_free (ui);
}
@@ -555,6 +527,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)

View File

@@ -121,6 +121,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);

View File

@@ -35,25 +35,6 @@
#include "meta-wayland-pointer.h"
#include "meta-wayland-private.h"
typedef struct
{
struct wl_resource *resource;
MetaWaylandDataSource *source;
struct wl_listener source_destroy_listener;
} MetaWaylandDataOffer;
struct _MetaWaylandDataSource
{
struct wl_resource *resource;
struct wl_array mime_types;
};
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
data_offer_accept (struct wl_client *client,
struct wl_resource *resource,
@@ -198,8 +179,7 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
MetaWaylandSeat *seat = drag_grab->seat;
struct wl_client *client;
struct wl_resource *data_device_resource, *offer = NULL;
struct wl_resource *resource, *offer = NULL;
struct wl_display *display;
guint32 serial;
wl_fixed_t sx, sy;
@@ -222,28 +202,28 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
wl_resource_get_client (surface->resource) != drag_grab->drag_client)
return;
client = wl_resource_get_client (surface->resource);
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
if (!data_device_resource)
resource =
wl_resource_find_for_client (&seat->data_device_resource_list,
wl_resource_get_client (surface->resource));
if (!resource)
return;
display = wl_client_get_display (client);
display = wl_client_get_display (wl_resource_get_client (resource));
serial = wl_display_next_serial (display);
if (drag_grab->drag_data_source)
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
data_device_resource);
resource);
meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
wl_data_device_send_enter (data_device_resource, serial, surface->resource,
wl_data_device_send_enter (resource, serial, surface->resource,
sx, sy, offer);
drag_grab->drag_focus = surface;
drag_grab->drag_focus_data_device = data_device_resource;
drag_grab->drag_focus_data_device = resource;
drag_grab->drag_focus_listener.notify = destroy_drag_focus;
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
wl_resource_add_destroy_listener (resource, &drag_grab->drag_focus_listener);
}
static void
@@ -332,8 +312,7 @@ data_device_start_drag (struct wl_client *client,
struct wl_resource *origin_resource,
struct wl_resource *icon_resource, guint32 serial)
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandDragGrab *drag_grab;
if ((seat->pointer.button_count == 0 ||
@@ -378,67 +357,68 @@ data_device_start_drag (struct wl_client *client,
static void
destroy_selection_data_source (struct wl_listener *listener, void *data)
{
MetaWaylandDataDevice *data_device = wl_container_of (listener, data_device, selection_data_source_listener);
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
MetaWaylandSeat *seat =
wl_container_of (listener, seat, selection_data_source_listener);
struct wl_resource *data_device;
struct wl_client *focus_client = NULL;
data_device->selection_data_source = NULL;
seat->selection_data_source = NULL;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
wl_data_device_send_selection (data_device_resource, NULL);
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
if (data_device)
wl_data_device_send_selection (data_device, NULL);
}
}
static void
meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial)
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
MetaWaylandDataSource *source,
guint32 serial)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource, *offer;
struct wl_resource *data_device, *offer;
struct wl_client *focus_client;
if (data_device->selection_data_source &&
data_device->selection_serial - serial < UINT32_MAX / 2)
if (seat->selection_data_source &&
seat->selection_serial - serial < UINT32_MAX / 2)
return;
if (data_device->selection_data_source)
if (seat->selection_data_source)
{
wl_data_source_send_cancelled (data_device->selection_data_source->resource);
wl_list_remove (&data_device->selection_data_source_listener.link);
data_device->selection_data_source = NULL;
wl_data_source_send_cancelled (seat->selection_data_source->resource);
wl_list_remove (&seat->selection_data_source_listener.link);
seat->selection_data_source = NULL;
}
data_device->selection_data_source = source;
data_device->selection_serial = serial;
seat->selection_data_source = source;
seat->selection_serial = serial;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
if (data_device)
{
if (data_device->selection_data_source)
if (seat->selection_data_source)
{
offer = meta_wayland_data_source_send_offer (data_device->selection_data_source, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
offer = meta_wayland_data_source_send_offer (seat->selection_data_source, data_device);
wl_data_device_send_selection (data_device, offer);
}
else
{
wl_data_device_send_selection (data_device_resource, NULL);
wl_data_device_send_selection (data_device, NULL);
}
}
}
if (source)
{
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
seat->selection_data_source_listener.notify =
destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource,
&seat->selection_data_source_listener);
}
}
@@ -448,16 +428,13 @@ data_device_set_selection (struct wl_client *client,
struct wl_resource *source_resource,
guint32 serial)
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandDataSource *source;
if (!source_resource)
return;
source = wl_resource_get_user_data (source_resource);
/* FIXME: Store serial and check against incoming serial here. */
meta_wayland_data_device_set_selection (data_device, source, serial);
meta_wayland_seat_set_selection (wl_resource_get_user_data (resource),
wl_resource_get_user_data (source_resource),
serial);
}
static const struct wl_data_device_interface data_device_interface = {
@@ -493,18 +470,25 @@ create_data_source (struct wl_client *client,
wl_array_init (&source->mime_types);
}
static void
unbind_data_device (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
get_data_device (struct wl_client *client,
struct wl_resource *manager_resource,
guint32 id, struct wl_resource *seat_resource)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
struct wl_resource *cr;
struct wl_resource *resource;
cr = wl_resource_create (client, &wl_data_device_interface,
MIN (META_WL_DATA_DEVICE_VERSION, wl_resource_get_version (manager_resource)), id);
wl_resource_set_implementation (cr, &data_device_interface, &seat->data_device, unbind_resource);
wl_list_insert (&seat->data_device.resource_list, wl_resource_get_link (cr));
resource = wl_resource_create (client, &wl_data_device_interface,
MIN (META_WL_DATA_DEVICE_VERSION,
wl_resource_get_version (manager_resource)), id);
wl_resource_set_implementation (resource, &data_device_interface, seat, unbind_data_device);
wl_list_insert (&seat->data_device_resource_list, wl_resource_get_link (resource));
}
static const struct wl_data_device_manager_interface manager_interface = {
@@ -534,31 +518,24 @@ meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
}
void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat)
{
wl_list_init (&data_device->resource_list);
}
void
meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_client *focus_client;
struct wl_resource *data_device_resource, *offer;
struct wl_resource *data_device, *offer;
MetaWaylandDataSource *source;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (!focus_client)
return;
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (!data_device_resource)
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
if (!data_device)
return;
source = data_device->selection_data_source;
source = seat->selection_data_source;
if (source)
{
offer = meta_wayland_data_source_send_offer (source, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
offer = meta_wayland_data_source_send_offer (source, data_device);
wl_data_device_send_selection (data_device, offer);
}
}

View File

@@ -25,20 +25,10 @@
#include <wayland-server.h>
#include "meta-wayland-types.h"
struct _MetaWaylandDataDevice
{
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
};
#include "meta-wayland-private.h"
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
#endif /* META_WAYLAND_DATA_DEVICE_H */

View File

@@ -301,7 +301,6 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
void
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
{
meta_wayland_keyboard_set_focus (keyboard, NULL);
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
xkb_context_unref (keyboard->xkb_context);
@@ -550,7 +549,7 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
cr = wl_resource_create (client, &wl_keyboard_interface,
MIN (META_WL_KEYBOARD_VERSION, wl_resource_get_version (seat_resource)), id);
wl_resource_set_implementation (cr, &keyboard_interface, keyboard, unbind_resource);
wl_resource_set_implementation (cr, NULL, keyboard, unbind_resource);
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
wl_keyboard_send_keymap (cr,

View File

@@ -168,20 +168,12 @@ wayland_output_destroy_notify (gpointer data)
g_slice_free (MetaWaylandOutput, wayland_output);
}
static inline enum wl_output_transform
wl_output_transform_from_meta_monitor_transform (MetaMonitorTransform transform)
{
/* The enums are the same. */
return (enum wl_output_transform) transform;
}
static void
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
MetaOutput *output)
{
GList *iter;
guint mode_flags;
enum wl_output_transform wl_transform = wl_output_transform_from_meta_monitor_transform (output->crtc->transform);
g_assert (output->crtc->current_mode != NULL);
@@ -195,7 +187,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
if (wayland_output->x != output->crtc->rect.x ||
wayland_output->y != output->crtc->rect.y ||
wayland_output->transform != wl_transform)
wayland_output->transform != output->crtc->transform)
{
wl_resource_post_event (resource,
WL_OUTPUT_GEOMETRY,
@@ -206,7 +198,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
output->subpixel_order,
output->vendor,
output->product,
wl_transform);
output->crtc->transform);
}
wl_resource_post_event (resource,
@@ -222,7 +214,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
wayland_output->output = output;
wayland_output->x = output->crtc->rect.x;
wayland_output->y = output->crtc->rect.y;
wayland_output->transform = wl_transform;
wayland_output->transform = output->crtc->transform;
}
static GHashTable *
@@ -244,15 +236,15 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
/* wayland does not expose disabled outputs */
if (output->crtc == NULL)
{
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
continue;
}
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
if (wayland_output)
{
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
}
else
{
@@ -264,7 +256,7 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
}
wayland_output_update_for_output (wayland_output, output);
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->winsys_id), wayland_output);
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
}
g_hash_table_destroy (compositor->outputs);

View File

@@ -207,14 +207,11 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
manager = clutter_device_manager_get_default ();
pointer->device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
pointer->cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
}
void
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
{
meta_wayland_pointer_set_focus (pointer, NULL);
set_cursor_surface (pointer, NULL);
}
@@ -816,7 +813,7 @@ meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface,
uint32_t serial)
{
return (pointer->button_count > 0 &&
return (pointer->button_count == 0 &&
pointer->grab_serial == serial &&
pointer->focus_surface == surface);
}

View File

@@ -50,6 +50,10 @@ typedef struct
typedef struct
{
struct wl_list link;
/* Pointer back to the compositor */
MetaWaylandCompositor *compositor;
struct wl_resource *resource;
} MetaWaylandFrameCallback;
@@ -71,8 +75,10 @@ struct _MetaWaylandCompositor
{
struct wl_display *wayland_display;
char *display_name;
struct wl_event_loop *wayland_loop;
ClutterActor *stage;
GHashTable *outputs;
GSource *wayland_event_source;
struct wl_list frame_callbacks;
MetaXWaylandManager xwayland_manager;

View File

@@ -25,7 +25,6 @@
#include "meta-wayland-private.h"
#include "meta-wayland-versions.h"
#include "meta-wayland-data-device.h"
static void
unbind_resource (struct wl_resource *resource)
@@ -100,12 +99,15 @@ meta_wayland_seat_new (struct wl_display *display)
{
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
seat->selection_data_source = NULL;
wl_list_init (&seat->base_resource_list);
wl_list_init (&seat->data_device_resource_list);
meta_wayland_pointer_init (&seat->pointer, display);
meta_wayland_keyboard_init (&seat->keyboard, display);
meta_wayland_touch_init (&seat->touch, display);
meta_wayland_data_device_init (&seat->data_device);
seat->display = display;
wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat);
@@ -191,14 +193,6 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat)
meta_wayland_pointer_repick (&seat->pointer);
}
void
meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
MetaWaylandSurface *surface)
{
meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
}
void
meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
{

View File

@@ -26,19 +26,37 @@
#include <clutter/clutter.h>
#include "meta-wayland-types.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-touch.h"
#include "meta-wayland-data-device.h"
struct _MetaWaylandDataOffer
{
struct wl_resource *resource;
MetaWaylandDataSource *source;
struct wl_listener source_destroy_listener;
};
struct _MetaWaylandDataSource
{
struct wl_resource *resource;
struct wl_array mime_types;
};
struct _MetaWaylandSeat
{
struct wl_list base_resource_list;
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list data_device_resource_list;
MetaWaylandPointer pointer;
MetaWaylandKeyboard keyboard;
MetaWaylandTouch touch;
MetaWaylandDataDevice data_device;
struct wl_display *display;
};
void meta_wayland_seat_init (MetaWaylandCompositor *compositor);
@@ -51,9 +69,6 @@ void meta_wayland_seat_update (MetaWaylandSeat *seat,
gboolean meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
const ClutterEvent *event);
void meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
MetaWaylandSurface *surface);
void meta_wayland_seat_repick (MetaWaylandSeat *seat);
void meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat);

View File

@@ -163,88 +163,33 @@ cursor_surface_commit (MetaWaylandSurface *surface,
}
static void
calculate_surface_window_geometry (MetaWaylandSurface *surface,
MetaRectangle *total_geometry,
float parent_x,
float parent_y)
{
ClutterActor *surface_actor = CLUTTER_ACTOR (surface->surface_actor);
MetaRectangle geom;
float x, y;
GList *l;
/* Unmapped surfaces don't count. */
if (!CLUTTER_ACTOR_IS_VISIBLE (surface_actor))
return;
/* XXX: Is there a better way to do this using Clutter APIs? */
clutter_actor_get_position (surface_actor, &x, &y);
geom.x = parent_x + x;
geom.y = parent_x + y;
geom.width = cogl_texture_get_width (surface->buffer->texture);
geom.height = cogl_texture_get_height (surface->buffer->texture);
meta_rectangle_union (total_geometry, &geom, total_geometry);
for (l = surface->subsurfaces; l != NULL; l = l->next)
{
MetaWaylandSurface *subsurface = l->data;
calculate_surface_window_geometry (subsurface, total_geometry, x, y);
}
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
toplevel_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaWindow *window = surface->window;
/* Sanity check. */
if (surface->buffer == NULL)
if (pending->newly_attached)
{
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Cannot commit a NULL buffer to an xdg_surface");
return;
MetaWindow *window = surface->window;
MetaWaylandBuffer *buffer = pending->buffer;
meta_window_set_surface_mapped (window, buffer != NULL);
/* We resize X based surfaces according to X events */
if (buffer != NULL && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
int new_width, new_height;
new_width = cogl_texture_get_width (buffer->texture);
new_height = cogl_texture_get_height (buffer->texture);
if (new_width != window->rect.width ||
new_height != window->rect.height ||
pending->dx != 0 ||
pending->dy != 0)
meta_window_wayland_move_resize (window, new_width, new_height, pending->dx, pending->dy);
}
}
/* We resize X based surfaces according to X events */
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
MetaRectangle geom;
if (pending->has_new_geometry)
{
/* If we have new geometry, use it. */
geom = pending->new_geometry;
surface->has_set_geometry = TRUE;
}
else if (!surface->has_set_geometry)
{
/* If the surface has never set any geometry, calculate
* a default one unioning the surface and all subsurfaces together. */
calculate_surface_window_geometry (surface, &geom, 0, 0);
}
else
{
/* Otherwise, keep the geometry the same. */
/* XXX: We don't store the geometry in any consistent place
* right now, so we can't re-fetch it. We should change
* meta_window_wayland_move_resize. */
/* XXX: This is the common case. Recognize it to prevent
* a warning. */
if (pending->dx == 0 && pending->dy == 0)
return;
g_warning ("XXX: Attach-initiated move without a new geometry. This is unimplemented right now.");
return;
}
meta_window_wayland_move_resize (window, geom, pending->dx, pending->dy);
}
if (pending->frame_extents_changed)
meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
}
static void
@@ -271,7 +216,7 @@ pending_state_init (MetaWaylandPendingState *state)
state->buffer_destroy_listener.notify = surface_handle_pending_buffer_destroy;
wl_list_init (&state->frame_callback_list);
state->has_new_geometry = FALSE;
state->frame_extents_changed = FALSE;
}
static void
@@ -317,18 +262,22 @@ static void
subsurface_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
float x, y;
if (pending->newly_attached)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
float x, y;
if (surface->buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
if (buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
}
}
static void
@@ -467,13 +416,16 @@ wl_surface_attach (struct wl_client *client,
else
buffer = NULL;
if (surface->buffer == buffer)
return;
if (surface->pending.buffer)
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
surface->pending.newly_attached = TRUE;
surface->pending.buffer = buffer;
surface->pending.dx = dx;
surface->pending.dy = dy;
surface->pending.buffer = buffer;
surface->pending.newly_attached = TRUE;
if (buffer)
wl_signal_add (&buffer->destroy_signal,
@@ -521,6 +473,7 @@ wl_surface_frame (struct wl_client *client,
return;
callback = g_slice_new0 (MetaWaylandFrameCallback);
callback->compositor = surface->compositor;
callback->resource = wl_resource_create (client, &wl_callback_interface, META_WL_CALLBACK_VERSION, callback_id);
wl_resource_set_implementation (callback->resource, NULL, callback, destroy_frame_callback);
@@ -780,6 +733,23 @@ xdg_surface_set_parent (struct wl_client *client,
meta_window_set_transient_for (surface->window, transient_for);
}
static void
xdg_surface_set_margin (struct wl_client *client,
struct wl_resource *resource,
int32_t left_margin,
int32_t right_margin,
int32_t top_margin,
int32_t bottom_margin)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->pending.frame_extents_changed = TRUE;
surface->pending.frame_extents.left = left_margin;
surface->pending.frame_extents.right = right_margin;
surface->pending.frame_extents.top = top_margin;
surface->pending.frame_extents.bottom = bottom_margin;
}
static void
xdg_surface_set_title (struct wl_client *client,
struct wl_resource *resource,
@@ -805,8 +775,8 @@ xdg_surface_show_window_menu (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *seat_resource,
uint32_t serial,
int32_t x,
int32_t y)
uint32_t x,
uint32_t y)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -910,20 +880,6 @@ xdg_surface_ack_configure (struct wl_client *client,
* client gets the new state. */
}
static void
xdg_surface_set_window_geometry (struct wl_client *client,
struct wl_resource *resource,
int32_t x, int32_t y, int32_t width, int32_t height)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->pending.has_new_geometry = TRUE;
surface->pending.new_geometry.x = x;
surface->pending.new_geometry.y = y;
surface->pending.new_geometry.width = width;
surface->pending.new_geometry.height = height;
}
static void
xdg_surface_set_maximized (struct wl_client *client,
struct wl_resource *resource)
@@ -968,13 +924,13 @@ xdg_surface_set_minimized (struct wl_client *client,
static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
xdg_surface_destroy,
xdg_surface_set_parent,
xdg_surface_set_margin,
xdg_surface_set_title,
xdg_surface_set_app_id,
xdg_surface_show_window_menu,
xdg_surface_move,
xdg_surface_resize,
xdg_surface_ack_configure,
xdg_surface_set_window_geometry,
xdg_surface_set_maximized,
xdg_surface_unset_maximized,
xdg_surface_set_fullscreen,
@@ -1116,17 +1072,20 @@ bind_xdg_shell (struct wl_client *client,
guint32 version,
guint32 id)
{
struct wl_resource *resource;
XdgShell *xdg_shell;
if (version != META_XDG_SHELL_VERSION)
if (version != 1)
{
g_warning ("using xdg-shell without stable version %d\n", META_XDG_SHELL_VERSION);
g_warning ("using xdg-shell without stable version 1\n");
return;
}
xdg_shell = g_slice_new (XdgShell);
xdg_shell->resource = wl_resource_create (client, &xdg_shell_interface, META_XDG_SHELL_VERSION, id);
resource = wl_resource_create (client, &xdg_shell_interface, 1, id);
wl_resource_set_implementation (resource, &meta_wayland_xdg_shell_interface, data, NULL);
xdg_shell->resource = wl_resource_create (client, &xdg_shell_interface, 1, id);
wl_resource_set_implementation (xdg_shell->resource, &meta_wayland_xdg_shell_interface, data, NULL);
xdg_shell->client_destroy_listener.notify = xdg_shell_handle_client_destroy;
@@ -1392,13 +1351,13 @@ gtk_surface_destructor (struct wl_resource *resource)
static void
set_dbus_properties (struct wl_client *client,
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -1424,9 +1383,9 @@ static const struct gtk_surface_interface meta_wayland_gtk_surface_interface = {
static void
get_gtk_surface (struct wl_client *client,
struct wl_resource *resource,
guint32 id,
struct wl_resource *surface_resource)
struct wl_resource *resource,
guint32 id,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
@@ -1450,14 +1409,14 @@ static const struct gtk_shell_interface meta_wayland_gtk_shell_interface = {
static void
bind_gtk_shell (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
void *data,
guint32 version,
guint32 id)
{
struct wl_resource *resource;
resource = wl_resource_create (client, &gtk_shell_interface,
MIN (META_GTK_SHELL_VERSION, version), id);
MIN (META_GTK_SHELL_VERSION, version), id);
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
/* FIXME: ask the plugin */
@@ -1744,7 +1703,7 @@ bind_subcompositor (struct wl_client *client,
struct wl_resource *resource;
resource = wl_resource_create (client, &wl_subcompositor_interface,
MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
wl_resource_set_implementation (resource, &meta_wayland_subcompositor_interface, data, NULL);
}
@@ -1752,21 +1711,19 @@ void
meta_wayland_shell_init (MetaWaylandCompositor *compositor)
{
if (wl_global_create (compositor->wayland_display,
&xdg_shell_interface,
META_XDG_SHELL_VERSION,
compositor, bind_xdg_shell) == NULL)
&xdg_shell_interface, 1,
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,
META_WL_SHELL_VERSION,
compositor, bind_wl_shell) == NULL)
&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,
&gtk_shell_interface,
META_GTK_SHELL_VERSION,
compositor, bind_gtk_shell) == NULL)
&gtk_shell_interface,
META_GTK_SHELL_VERSION,
compositor, bind_gtk_shell) == NULL)
g_error ("Failed to register a global gtk-shell object");
if (wl_global_create (compositor->wayland_display,
@@ -1805,8 +1762,8 @@ fill_states (struct wl_array *states, MetaWindow *window)
void
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int new_width,
int new_height)
int new_width,
int new_height)
{
if (surface->xdg_surface.resource)
{

View File

@@ -61,8 +61,8 @@ typedef struct
/* wl_surface.frame */
struct wl_list frame_callback_list;
MetaRectangle new_geometry;
gboolean has_new_geometry;
gboolean frame_extents_changed;
GtkBorder frame_extents;
} MetaWaylandPendingState;
typedef struct
@@ -109,8 +109,6 @@ struct _MetaWaylandSurface
GSList *pending_placement_ops;
} sub;
gboolean has_set_geometry;
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
};

View File

@@ -444,29 +444,6 @@ touch_info_free (MetaWaylandTouchInfo *touch_info)
g_free (touch_info);
}
static void
touch_handle_cancel_event (MetaWaylandTouch *touch,
struct libinput_event *event)
{
GList *surfaces, *s;
surfaces = s = touch_get_surfaces (touch, FALSE);
while (s)
{
MetaWaylandTouchSurface *touch_surface = s->data;
struct wl_resource *resource;
struct wl_list *l;
l = &touch_surface->resource_list;
wl_resource_for_each(resource, l)
wl_touch_send_cancel (resource);
}
g_hash_table_remove_all (touch->touches);
g_list_free (surfaces);
}
static gboolean
evdev_filter_func (struct libinput_event *event,
gpointer data)
@@ -495,7 +472,7 @@ evdev_filter_func (struct libinput_event *event,
* which are not so useful when sending a global signal as the protocol
* requires.
*/
touch_handle_cancel_event (touch, event);
meta_wayland_touch_cancel (touch);
break;
default:
break;
@@ -543,6 +520,28 @@ meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
cr = wl_resource_create (client, &wl_touch_interface,
MIN (META_WL_TOUCH_VERSION, wl_resource_get_version (seat_resource)), id);
wl_resource_set_implementation (cr, &touch_interface, touch, unbind_resource);
wl_resource_set_implementation (cr, NULL, touch, unbind_resource);
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
}
void
meta_wayland_touch_cancel (MetaWaylandTouch *touch)
{
GList *surfaces, *s;
surfaces = s = touch_get_surfaces (touch, FALSE);
while (s)
{
MetaWaylandTouchSurface *touch_surface = s->data;
struct wl_resource *resource;
struct wl_list *l;
l = &touch_surface->resource_list;
wl_resource_for_each(resource, l)
wl_touch_send_cancel (resource);
}
g_hash_table_remove_all (touch->touches);
g_list_free (surfaces);
}

View File

@@ -58,5 +58,7 @@ void meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id);
void meta_wayland_touch_cancel (MetaWaylandTouch *touch);
#endif /* META_WAYLAND_TOUCH_H */

View File

@@ -27,9 +27,9 @@ typedef struct _MetaWaylandPointer MetaWaylandPointer;
typedef struct _MetaWaylandPointerGrab MetaWaylandPointerGrab;
typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;

View File

@@ -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_XDG_SHELL_VERSION 1
#define META_WL_SHELL_VERSION 1
#define META_WL_SEAT_VERSION 3
#define META_WL_OUTPUT_VERSION 2

View File

@@ -187,7 +187,9 @@ meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
{
MetaWaylandSurface *surface = window ? window->surface : NULL;
meta_wayland_seat_set_input_focus (compositor->seat, surface);
meta_wayland_keyboard_set_focus (&compositor->seat->keyboard,
surface);
meta_wayland_data_device_set_keyboard_focus (compositor->seat);
}
void
@@ -382,7 +384,6 @@ void
meta_wayland_init (void)
{
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
GSource *wayland_event_source;
memset (compositor, 0, sizeof (MetaWaylandCompositor));
@@ -401,7 +402,10 @@ meta_wayland_init (void)
compositor, compositor_bind))
g_error ("Failed to register wayland compositor object");
wayland_event_source = wayland_event_source_new (compositor->wayland_display);
compositor->wayland_loop =
wl_display_get_event_loop (compositor->wayland_display);
compositor->wayland_event_source =
wayland_event_source_new (compositor->wayland_display);
/* XXX: Here we are setting the wayland event source to have a
* slightly lower priority than the X event source, because we are
@@ -412,8 +416,9 @@ meta_wayland_init (void)
* At some point we could perhaps try and get the X protocol proxied
* over the wayland protocol so that we don't have to worry about
* synchronizing the two command streams. */
g_source_set_priority (wayland_event_source, GDK_PRIORITY_EVENTS + 1);
g_source_attach (wayland_event_source, NULL);
g_source_set_priority (compositor->wayland_event_source,
GDK_PRIORITY_EVENTS + 1);
g_source_attach (compositor->wayland_event_source, NULL);
clutter_wayland_set_compositor_display (compositor->wayland_display);
meta_clutter_init ();

View File

@@ -146,6 +146,32 @@
<arg name="parent" type="object" interface="wl_surface" allow-null="true"/>
</request>
<request name="set_margin">
<description summary="set the visible frame boundaries">
This tells the compositor what the visible size of the window
should be, so it can use it to determine what borders to use for
constrainment and alignment.
CSD often has invisible areas for decoration purposes, like drop
shadows. These "shadow" drawings need to be subtracted out of the
normal boundaries of the window when computing where to place
windows (e.g. to set this window so it's centered on top of another,
or to put it to the left or right of the screen.)
This value should change as little as possible at runtime, to
prevent flicker.
This value is also ignored when the window is maximized or
fullscreen, and assumed to be 0.
If never called, this value is assumed to be 0.
</description>
<arg name="left_margin" type="int"/>
<arg name="right_margin" type="int"/>
<arg name="top_margin" type="int"/>
<arg name="bottom_margin" type="int"/>
</request>
<request name="set_title">
<description summary="set surface title">
Set a short title for the surface.
@@ -178,18 +204,14 @@
a context menu when right-clicking on the decorations, giving the
user a menu that they can use to maximize or minimize the window.
This request asks the compositor to pop up such a window menu at
the given position, relative to the parent surface. There are
no guarantees as to what the window menu contains.
Your surface must have focus on the seat passed in to pop up the
window menu.
The seat passed must have either pointer or keyboard focus to pop
up the window menu for a surface.
</description>
<arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/>
<arg name="serial" type="uint" summary="serial of the event to pop up the window for"/>
<arg name="x" type="int" summary="the x position to pop up the window menu at"/>
<arg name="y" type="int" summary="the y position to pop up the window menu at"/>
<arg name="x" type="uint"/>
<arg name="y" type="uint"/>
</request>
<request name="move">
@@ -278,11 +300,11 @@
</enum>
<event name="configure">
<description summary="suggest a surface change">
<description summary="suggest a surface chnage">
The configure event asks the client to resize its surface.
The width and height arguments specify a hint to the window
about how its surface should be resized in window geometry
about how its surface should be resized in surface local
coordinates. The states listed in the event specify how the
width/height arguments should be interpreted.
@@ -313,29 +335,6 @@
<arg name="serial" type="uint" summary="a serial to configure for"/>
</request>
<request name="set_window_geometry">
<description summary="set the new window geometry">
The window geometry of a window is its "visible bounds" from the
user's perspective. Client-side decorations often have invisible
portions like drop-shadows which should be ignored for the
purposes of aligning, placing and constraining windows.
The default value is the full bounds of the surface, including any
subsurfaces. Once the window geometry of the surface is set once,
it is not possible to unset it, and it will remain the same until
set_window_geometry is called again, even if a new subsurface or
buffer is attached.
If responding to a configure event, the window geometry in here
must respect the sizing negotiations specified by the states in
the configure event.
</description>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</request>
<request name="set_maximized" />
<request name="unset_maximized" />

View File

@@ -133,8 +133,7 @@ static void
meta_window_wayland_grab_op_began (MetaWindow *window,
MetaGrabOp op)
{
if (meta_grab_op_is_resizing (op))
surface_state_changed (window);
surface_state_changed (window);
META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_began (window, op);
}
@@ -143,8 +142,7 @@ static void
meta_window_wayland_grab_op_ended (MetaWindow *window,
MetaGrabOp op)
{
if (meta_grab_op_is_resizing (op))
surface_state_changed (window);
surface_state_changed (window);
META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_ended (window, op);
}
@@ -178,24 +176,9 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
* update the real client size to match the buffer size.
*/
if (window->rect.width != unconstrained_rect.width ||
window->rect.height != unconstrained_rect.height)
{
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
window->rect.width = unconstrained_rect.width;
window->rect.height = unconstrained_rect.height;
}
CoglTexture *texture = window->surface->buffer->texture;
int new_buffer_width = cogl_texture_get_width (texture);
int new_buffer_height = cogl_texture_get_height (texture);
if (window->buffer_rect.width != new_buffer_width ||
window->buffer_rect.height != new_buffer_height)
{
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
window->buffer_rect.width = new_buffer_width;
window->buffer_rect.height = new_buffer_height;
}
*result |= META_MOVE_RESIZE_RESULT_RESIZED;
window->rect.width = unconstrained_rect.width;
window->rect.height = unconstrained_rect.height;
/* This is a commit of an attach. We should move the window to match the
* new position the client wants. */
@@ -234,16 +217,6 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
window->rect.x = new_x;
window->rect.y = new_y;
}
int new_buffer_x = new_x - window->custom_frame_extents.left;
int new_buffer_y = new_y - window->custom_frame_extents.top;
if (new_buffer_x != window->buffer_rect.x || new_buffer_y != window->buffer_rect.y)
{
*result |= META_MOVE_RESIZE_RESULT_MOVED;
window->buffer_rect.x = new_buffer_x;
window->buffer_rect.y = new_buffer_y;
}
}
}
@@ -349,20 +322,17 @@ meta_window_wayland_new (MetaDisplay *display,
* Complete a resize operation from a wayland client.
*/
void
meta_window_wayland_move_resize (MetaWindow *window,
MetaRectangle new_geom,
int dx,
int dy)
meta_window_wayland_move_resize (MetaWindow *window,
int width,
int height,
int dx,
int dy)
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
int gravity;
MetaRectangle rect;
MetaMoveResizeFlags flags;
/* XXX: Find a better place to store the window geometry offsets. */
window->custom_frame_extents.left = new_geom.x;
window->custom_frame_extents.top = new_geom.y;
flags = META_IS_WAYLAND_RESIZE;
/* x/y are ignored when we're doing interactive resizing */
@@ -377,8 +347,7 @@ meta_window_wayland_move_resize (MetaWindow *window,
}
else
{
rect.x = window->rect.x;
rect.y = window->rect.y;
meta_window_get_frame_rect (window, &rect);
}
if (dx != 0 || dy != 0)
@@ -389,8 +358,10 @@ meta_window_wayland_move_resize (MetaWindow *window,
}
}
rect.width = new_geom.width;
rect.height = new_geom.height;
rect.width = width;
rect.height = height;
window->buffer_rect = rect;
if (rect.width != window->rect.width || rect.height != window->rect.height)
flags |= META_IS_RESIZE_ACTION;

View File

@@ -45,9 +45,10 @@ typedef struct _MetaWindowWaylandClass MetaWindowWaylandClass;
MetaWindow * meta_window_wayland_new (MetaDisplay *display,
MetaWaylandSurface *surface);
void meta_window_wayland_move_resize (MetaWindow *window,
MetaRectangle new_geom,
int dx,
int dy);
void meta_window_wayland_move_resize (MetaWindow *window,
int width,
int height,
int dx,
int dy);
#endif

View File

@@ -38,6 +38,16 @@
#include "wayland/meta-xwayland.h"
#include "wayland/meta-wayland-private.h"
typedef struct _EventFuncData EventFuncData;
struct _EventFuncData
{
GFunc func;
gpointer data;
};
static GList *event_funcs = NULL;
static XIEvent *
get_input_event (MetaDisplay *display,
XEvent *event)
@@ -1148,7 +1158,7 @@ process_selection_request (MetaDisplay *display,
meta_verbose ("Handled selection request\n");
}
static gboolean
static void
process_selection_clear (MetaDisplay *display,
XEvent *event)
{
@@ -1169,7 +1179,7 @@ process_selection_clear (MetaDisplay *display,
meta_XFree (str);
return FALSE;
return;
}
meta_verbose ("Got selection clear for screen %d on display %s\n",
@@ -1177,7 +1187,6 @@ process_selection_clear (MetaDisplay *display,
meta_display_unmanage_screen (display, display->screen,
event->xselectionclear.time);
return TRUE;
}
static gboolean
@@ -1773,14 +1782,13 @@ meta_display_handle_xevent (MetaDisplay *display,
if (event->type == SelectionClear)
{
if (process_selection_clear (display, event))
{
/* This means we called meta_display_unmanage_screen, which
* means the MetaDisplay is effectively dead. We don't want
* to poke into display->current_time below, since that would
* crash, so just directly return. */
return TRUE;
}
/* Do this here so we can return without any further
* processing. */
process_selection_clear (display, event);
/* Note that processing that may have resulted in
* closing the display... */
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
out:
@@ -1803,11 +1811,37 @@ xevent_filter (GdkXEvent *xevent,
gpointer data)
{
MetaDisplay *display = data;
EventFuncData *event_data;
XIEvent *input_event;
GList *l;
if (meta_display_handle_xevent (display, xevent))
return GDK_FILTER_REMOVE;
else
meta_display_handle_xevent (display, xevent);
for (l = event_funcs; l; l = l->next)
{
event_data = l->data;
event_data->func (xevent, event_data->data);
}
input_event = get_input_event (display, xevent);
if (!input_event)
return GDK_FILTER_CONTINUE;
/* Filter all pointer and touch events, those are emulated
* above by the filters, and Gdk is bypassed there on purpose.
*/
if (input_event->evtype == XI_ButtonPress ||
input_event->evtype == XI_ButtonRelease ||
input_event->evtype == XI_Motion ||
input_event->evtype == XI_Enter ||
input_event->evtype == XI_Leave ||
input_event->evtype == XI_TouchBegin ||
input_event->evtype == XI_TouchUpdate ||
input_event->evtype == XI_TouchEnd)
return GDK_FILTER_REMOVE;
return GDK_FILTER_CONTINUE;
}
void
@@ -1821,3 +1855,37 @@ meta_display_free_events_x11 (MetaDisplay *display)
{
gdk_window_remove_filter (NULL, xevent_filter, display);
}
void
meta_display_events_x11_add_func (GFunc func,
gpointer user_data)
{
EventFuncData *data;
data = g_slice_new0 (EventFuncData);
data->func = func;
data->data = user_data;
event_funcs = g_list_prepend (event_funcs, data);
}
void
meta_display_events_x11_remove_func (GFunc func,
gpointer user_data)
{
EventFuncData *data;
GList *l;
data = g_slice_new0 (EventFuncData);
for (l = event_funcs; l; l = l->next)
{
data = l->data;
if (data->func != func || data->data != user_data)
continue;
event_funcs = g_list_delete_link (event_funcs, l);
g_slice_free (EventFuncData, data);
break;
}
}

View File

@@ -28,4 +28,9 @@
void meta_display_init_events_x11 (MetaDisplay *display);
void meta_display_free_events_x11 (MetaDisplay *display);
void meta_display_events_x11_add_func (GFunc func,
gpointer user_data);
void meta_display_events_x11_remove_func (GFunc func,
gpointer user_data);
#endif

View File

@@ -28,6 +28,22 @@
/* The icon-reading code is also in libwnck, please sync bugfixes */
static void
get_fallback_icons (MetaScreen *screen,
GdkPixbuf **iconp,
int ideal_width,
int ideal_height,
GdkPixbuf **mini_iconp,
int ideal_mini_width,
int ideal_mini_height)
{
/* we don't scale, should be fixed if we ever un-hardcode the icon
* size
*/
*iconp = meta_ui_get_default_window_icon (screen->ui);
*mini_iconp = meta_ui_get_default_mini_icon (screen->ui);
}
static gboolean
find_largest_sizes (gulong *data,
gulong nitems,
@@ -526,11 +542,50 @@ meta_icon_cache_init (MetaIconCache *icon_cache)
icon_cache->origin = USING_NO_ICON;
icon_cache->prev_pixmap = None;
icon_cache->prev_mask = None;
#if 0
icon_cache->icon = NULL;
icon_cache->mini_icon = NULL;
icon_cache->ideal_width = -1; /* won't be a legit width */
icon_cache->ideal_height = -1;
icon_cache->ideal_mini_width = -1;
icon_cache->ideal_mini_height = -1;
#endif
icon_cache->want_fallback = TRUE;
icon_cache->wm_hints_dirty = TRUE;
icon_cache->kwm_win_icon_dirty = TRUE;
icon_cache->net_wm_icon_dirty = TRUE;
}
static void
clear_icon_cache (MetaIconCache *icon_cache,
gboolean dirty_all)
{
#if 0
if (icon_cache->icon)
g_object_unref (G_OBJECT (icon_cache->icon));
icon_cache->icon = NULL;
if (icon_cache->mini_icon)
g_object_unref (G_OBJECT (icon_cache->mini_icon));
icon_cache->mini_icon = NULL;
#endif
icon_cache->origin = USING_NO_ICON;
if (dirty_all)
{
icon_cache->wm_hints_dirty = TRUE;
icon_cache->kwm_win_icon_dirty = TRUE;
icon_cache->net_wm_icon_dirty = TRUE;
}
}
void
meta_icon_cache_free (MetaIconCache *icon_cache)
{
clear_icon_cache (icon_cache, FALSE);
}
void
meta_icon_cache_property_changed (MetaIconCache *icon_cache,
MetaDisplay *display,
@@ -556,12 +611,41 @@ meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache)
else if (icon_cache->origin <= USING_NET_WM_ICON &&
icon_cache->net_wm_icon_dirty)
return TRUE;
else if (icon_cache->origin < USING_FALLBACK_ICON)
else if (icon_cache->origin < USING_FALLBACK_ICON &&
icon_cache->want_fallback)
return TRUE;
else if (icon_cache->origin == USING_NO_ICON)
return TRUE;
else if (icon_cache->origin == USING_FALLBACK_ICON &&
!icon_cache->want_fallback)
return TRUE;
else
return FALSE;
}
static void
replace_cache (MetaIconCache *icon_cache,
IconOrigin origin,
GdkPixbuf *new_icon,
GdkPixbuf *new_mini_icon)
{
clear_icon_cache (icon_cache, FALSE);
icon_cache->origin = origin;
#if 0
if (new_icon)
g_object_ref (G_OBJECT (new_icon));
icon_cache->icon = new_icon;
if (new_mini_icon)
g_object_ref (G_OBJECT (new_mini_icon));
icon_cache->mini_icon = new_mini_icon;
#endif
}
static GdkPixbuf*
scaled_from_pixdata (guchar *pixdata,
int w,
@@ -631,6 +715,13 @@ meta_read_icons (MetaScreen *screen,
int ideal_mini_width,
int ideal_mini_height)
{
guchar *pixdata;
int w, h;
guchar *mini_pixdata;
int mini_w, mini_h;
Pixmap pixmap;
Pixmap mask;
/* Return value is whether the icon changed */
g_return_val_if_fail (icon_cache != NULL, FALSE);
@@ -638,9 +729,24 @@ meta_read_icons (MetaScreen *screen,
*iconp = NULL;
*mini_iconp = NULL;
#if 0
if (ideal_width != icon_cache->ideal_width ||
ideal_height != icon_cache->ideal_height ||
ideal_mini_width != icon_cache->ideal_mini_width ||
ideal_mini_height != icon_cache->ideal_mini_height)
clear_icon_cache (icon_cache, TRUE);
icon_cache->ideal_width = ideal_width;
icon_cache->ideal_height = ideal_height;
icon_cache->ideal_mini_width = ideal_mini_width;
icon_cache->ideal_mini_height = ideal_mini_height;
#endif
if (!meta_icon_cache_get_icon_invalidated (icon_cache))
return FALSE; /* we have no new info to use */
pixdata = NULL;
/* Our algorithm here assumes that we can't have for example origin
* < USING_NET_WM_ICON and icon_cache->net_wm_icon_dirty == FALSE
* unless we have tried to read NET_WM_ICON.
@@ -652,12 +758,8 @@ meta_read_icons (MetaScreen *screen,
if (icon_cache->origin <= USING_NET_WM_ICON &&
icon_cache->net_wm_icon_dirty)
{
guchar *pixdata;
int w, h;
guchar *mini_pixdata;
int mini_w, mini_h;
{
icon_cache->net_wm_icon_dirty = FALSE;
if (read_rgb_icon (screen->display, xwindow,
@@ -674,7 +776,9 @@ meta_read_icons (MetaScreen *screen,
if (*iconp && *mini_iconp)
{
icon_cache->origin = USING_NET_WM_ICON;
replace_cache (icon_cache, USING_NET_WM_ICON,
*iconp, *mini_iconp);
return TRUE;
}
else
@@ -690,9 +794,6 @@ meta_read_icons (MetaScreen *screen,
if (icon_cache->origin <= USING_WM_HINTS &&
icon_cache->wm_hints_dirty)
{
Pixmap pixmap;
Pixmap mask;
icon_cache->wm_hints_dirty = FALSE;
pixmap = wm_hints_pixmap;
@@ -713,7 +814,10 @@ meta_read_icons (MetaScreen *screen,
{
icon_cache->prev_pixmap = pixmap;
icon_cache->prev_mask = mask;
icon_cache->origin = USING_WM_HINTS;
replace_cache (icon_cache, USING_WM_HINTS,
*iconp, *mini_iconp);
return TRUE;
}
}
@@ -722,9 +826,6 @@ meta_read_icons (MetaScreen *screen,
if (icon_cache->origin <= USING_KWM_WIN_ICON &&
icon_cache->kwm_win_icon_dirty)
{
Pixmap pixmap;
Pixmap mask;
icon_cache->kwm_win_icon_dirty = FALSE;
get_kwm_win_icon (screen->display, xwindow, &pixmap, &mask);
@@ -739,17 +840,38 @@ meta_read_icons (MetaScreen *screen,
{
icon_cache->prev_pixmap = pixmap;
icon_cache->prev_mask = mask;
icon_cache->origin = USING_KWM_WIN_ICON;
replace_cache (icon_cache, USING_KWM_WIN_ICON,
*iconp, *mini_iconp);
return TRUE;
}
}
}
if (icon_cache->origin < USING_FALLBACK_ICON)
if (icon_cache->want_fallback &&
icon_cache->origin < USING_FALLBACK_ICON)
{
icon_cache->origin = USING_FALLBACK_ICON;
*iconp = NULL;
*mini_iconp = NULL;
get_fallback_icons (screen,
iconp,
ideal_width,
ideal_height,
mini_iconp,
ideal_mini_width,
ideal_mini_height);
replace_cache (icon_cache, USING_FALLBACK_ICON,
*iconp, *mini_iconp);
return TRUE;
}
if (!icon_cache->want_fallback &&
icon_cache->origin == USING_FALLBACK_ICON)
{
/* Get rid of current icon */
clear_icon_cache (icon_cache, FALSE);
return TRUE;
}

View File

@@ -44,6 +44,7 @@ struct _MetaIconCache
int origin;
Pixmap prev_pixmap;
Pixmap prev_mask;
guint want_fallback : 1;
/* TRUE if these props have changed */
guint wm_hints_dirty : 1;
guint kwm_win_icon_dirty : 1;
@@ -51,6 +52,7 @@ struct _MetaIconCache
};
void meta_icon_cache_init (MetaIconCache *icon_cache);
void meta_icon_cache_free (MetaIconCache *icon_cache);
void meta_icon_cache_property_changed (MetaIconCache *icon_cache,
MetaDisplay *display,
Atom atom);

View File

@@ -59,19 +59,13 @@ typedef void (* ReloadValueFunc) (MetaWindow *window,
MetaPropValue *value,
gboolean initial);
typedef enum {
NONE = 0,
LOAD_INIT = (1 << 0),
INCLUDE_OR = (1 << 1),
INIT_ONLY = (1 << 2),
} MetaPropHookFlags;
struct _MetaWindowPropHooks
{
Atom property;
MetaPropValueType type;
ReloadValueFunc reload_func;
MetaPropHookFlags flags;
gboolean load_initially;
gboolean include_override_redirect;
};
static void init_prop_value (MetaWindow *window,
@@ -98,9 +92,6 @@ meta_window_reload_property_from_xwindow (MetaWindow *window,
if (!hooks)
return;
if ((hooks->flags & INIT_ONLY) && !initial)
return;
init_prop_value (window, hooks, &value);
meta_prop_get_values (window->display, xwindow,
@@ -136,7 +127,7 @@ meta_window_load_initial_properties (MetaWindow *window)
for (i = 0; i < window->display->n_prop_hooks; i++)
{
MetaWindowPropHooks *hooks = &window->display->prop_hooks_table[i];
if (hooks->flags & LOAD_INIT)
if (hooks->load_initially)
{
init_prop_value (window, hooks, &values[j]);
++j;
@@ -151,7 +142,7 @@ meta_window_load_initial_properties (MetaWindow *window)
for (i = 0; i < window->display->n_prop_hooks; i++)
{
MetaWindowPropHooks *hooks = &window->display->prop_hooks_table[i];
if (hooks->flags & LOAD_INIT)
if (hooks->load_initially)
{
/* If we didn't actually manage to load anything then we don't need
* to call the reload function; this is different from a notification
@@ -175,7 +166,7 @@ init_prop_value (MetaWindow *window,
MetaPropValue *value)
{
if (!hooks || hooks->type == META_PROP_VALUE_INVALID ||
(window->override_redirect && !(hooks->flags & INCLUDE_OR)))
(window->override_redirect && !hooks->include_override_redirect))
{
value->type = META_PROP_VALUE_INVALID;
value->atom = None;
@@ -193,7 +184,8 @@ reload_prop_value (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (!(window->override_redirect && !(hooks->flags & INCLUDE_OR)))
if (hooks && hooks->reload_func != NULL &&
!(window->override_redirect && !hooks->include_override_redirect))
(* hooks->reload_func) (window, value, initial);
}
@@ -239,52 +231,14 @@ reload_net_wm_window_type (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = window_x11->priv;
if (value->type != META_PROP_VALUE_INVALID)
{
int i;
for (i = 0; i < value->v.atom_list.n_atoms; i++)
{
Atom atom = value->v.atom_list.atoms[i];
/* We break as soon as we find one we recognize,
* supposed to prefer those near the front of the list
*/
if (atom == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_DOCK ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_MENU ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_TOOLTIP ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_COMBO ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_DND ||
atom == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL)
{
priv->type_atom = atom;
break;
}
}
}
meta_window_x11_recalc_window_type (window);
meta_window_x11_update_net_wm_type (window);
}
static void
reload_icon (MetaWindow *window,
Atom atom)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = window_x11->priv;
meta_icon_cache_property_changed (&priv->icon_cache,
meta_icon_cache_property_changed (&window->icon_cache,
window->display,
atom);
meta_window_queue(window, META_QUEUE_UPDATE_ICON);
@@ -380,9 +334,7 @@ reload_wm_window_role (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
g_clear_pointer (&window->role, g_free);
if (value->type != META_PROP_VALUE_INVALID)
window->role = g_strdup (value->v.str);
meta_window_x11_update_role (window);
}
static void
@@ -610,72 +562,12 @@ reload_wm_name (MetaWindow *window,
}
}
static void
meta_window_set_opaque_region (MetaWindow *window,
cairo_region_t *region)
{
if (cairo_region_equal (window->opaque_region, region))
return;
g_clear_pointer (&window->opaque_region, cairo_region_destroy);
if (region != NULL)
window->opaque_region = cairo_region_reference (region);
meta_compositor_window_shape_changed (window->display->compositor, window);
}
static void
reload_opaque_region (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
cairo_region_t *opaque_region = NULL;
if (value->type != META_PROP_VALUE_INVALID)
{
gulong *region = value->v.cardinal_list.cardinals;
int nitems = value->v.cardinal_list.n_cardinals;
cairo_rectangle_int_t *rects;
int i, rect_index, nrects;
if (nitems % 4 != 0)
{
meta_verbose ("_NET_WM_OPAQUE_REGION does not have a list of 4-tuples.");
goto out;
}
/* empty region */
if (nitems == 0)
goto out;
nrects = nitems / 4;
rects = g_new (cairo_rectangle_int_t, nrects);
rect_index = 0;
i = 0;
while (i < nitems)
{
cairo_rectangle_int_t *rect = &rects[rect_index];
rect->x = region[i++];
rect->y = region[i++];
rect->width = region[i++];
rect->height = region[i++];
rect_index++;
}
opaque_region = cairo_region_create_rectangles (rects, nrects);
g_free (rects);
}
out:
meta_window_set_opaque_region (window, opaque_region);
cairo_region_destroy (opaque_region);
meta_window_x11_update_opaque_region (window);
}
static void
@@ -1498,8 +1390,6 @@ reload_wm_hints (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = window_x11->priv;
Window old_group_leader;
gboolean urgent;
@@ -1509,8 +1399,8 @@ reload_wm_hints (MetaWindow *window,
window->input = TRUE;
window->initially_iconic = FALSE;
window->xgroup_leader = None;
priv->wm_hints_pixmap = None;
priv->wm_hints_mask = None;
window->wm_hints_pixmap = None;
window->wm_hints_mask = None;
urgent = FALSE;
if (value->type != META_PROP_VALUE_INVALID)
@@ -1527,10 +1417,10 @@ reload_wm_hints (MetaWindow *window,
window->xgroup_leader = hints->window_group;
if (hints->flags & IconPixmapHint)
priv->wm_hints_pixmap = hints->icon_pixmap;
window->wm_hints_pixmap = hints->icon_pixmap;
if (hints->flags & IconMaskHint)
priv->wm_hints_mask = hints->icon_mask;
window->wm_hints_mask = hints->icon_mask;
if (hints->flags & XUrgencyHint)
urgent = TRUE;
@@ -1538,8 +1428,8 @@ reload_wm_hints (MetaWindow *window,
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
window->input, window->initially_iconic,
window->xgroup_leader,
priv->wm_hints_pixmap,
priv->wm_hints_mask);
window->wm_hints_pixmap,
window->wm_hints_mask);
}
if (window->xgroup_leader != old_group_leader)
@@ -1552,7 +1442,7 @@ reload_wm_hints (MetaWindow *window,
meta_window_set_urgent (window, urgent);
meta_icon_cache_property_changed (&priv->icon_cache,
meta_icon_cache_property_changed (&window->icon_cache,
window->display,
XA_WM_HINTS);
@@ -1758,7 +1648,10 @@ RELOAD_STRING (gtk_menubar_object_path, "gtk-menubar-object-path")
void
meta_display_init_window_prop_hooks (MetaDisplay *display)
{
/* The ordering here is significant for the properties we load
/* INIT: load initially
* O-R: fetch for override-redirect windows
*
* The ordering here is significant for the properties we load
* initially: they are roughly ordered in the order we want them to
* be gotten. We want to get window name and class first so we can
* use them in error messages and such. However, name is modified
@@ -1771,45 +1664,46 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
* - NET_WM_WINDOW_TYPE: can be used to do appropriate handling
* for different types of override-redirect windows.
*/
MetaWindowPropHooks hooks[] = {
{ display->atom_WM_CLIENT_MACHINE, META_PROP_VALUE_STRING, reload_wm_client_machine, LOAD_INIT | INCLUDE_OR },
{ display->atom__NET_WM_NAME, META_PROP_VALUE_UTF8, reload_net_wm_name, LOAD_INIT | INCLUDE_OR },
{ XA_WM_CLASS, META_PROP_VALUE_CLASS_HINT, reload_wm_class, LOAD_INIT | INCLUDE_OR },
{ display->atom__NET_WM_PID, META_PROP_VALUE_CARDINAL, reload_net_wm_pid, LOAD_INIT | INCLUDE_OR },
{ XA_WM_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name, LOAD_INIT | INCLUDE_OR },
{ display->atom__MUTTER_HINTS, META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, LOAD_INIT | INCLUDE_OR },
{ display->atom__NET_WM_OPAQUE_REGION, META_PROP_VALUE_CARDINAL_LIST, reload_opaque_region, LOAD_INIT | INCLUDE_OR },
{ display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, LOAD_INIT | INIT_ONLY },
{ display->atom__NET_STARTUP_ID, META_PROP_VALUE_UTF8, reload_net_startup_id, LOAD_INIT },
{ display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER_LIST, reload_update_counter, LOAD_INIT | INCLUDE_OR },
{ XA_WM_NORMAL_HINTS, META_PROP_VALUE_SIZE_HINTS, reload_normal_hints, LOAD_INIT },
{ display->atom_WM_PROTOCOLS, META_PROP_VALUE_ATOM_LIST, reload_wm_protocols, LOAD_INIT },
{ XA_WM_HINTS, META_PROP_VALUE_WM_HINTS, reload_wm_hints, LOAD_INIT },
{ display->atom__NET_WM_USER_TIME, META_PROP_VALUE_CARDINAL, reload_net_wm_user_time, LOAD_INIT },
{ display->atom__NET_WM_STATE, META_PROP_VALUE_ATOM_LIST, reload_net_wm_state, LOAD_INIT | INIT_ONLY },
{ display->atom__MOTIF_WM_HINTS, META_PROP_VALUE_MOTIF_HINTS, reload_mwm_hints, LOAD_INIT },
{ XA_WM_TRANSIENT_FOR, META_PROP_VALUE_WINDOW, reload_transient_for, LOAD_INIT },
{ display->atom__GTK_THEME_VARIANT, META_PROP_VALUE_UTF8, reload_gtk_theme_variant, LOAD_INIT },
{ display->atom__GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED, META_PROP_VALUE_CARDINAL, reload_gtk_hide_titlebar_when_maximized, LOAD_INIT },
{ display->atom__GTK_APPLICATION_ID, META_PROP_VALUE_UTF8, reload_gtk_application_id, LOAD_INIT },
{ display->atom__GTK_UNIQUE_BUS_NAME, META_PROP_VALUE_UTF8, reload_gtk_unique_bus_name, LOAD_INIT },
{ display->atom__GTK_APPLICATION_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_application_object_path, LOAD_INIT },
{ display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, LOAD_INIT },
{ display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, LOAD_INIT },
{ display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, LOAD_INIT },
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, LOAD_INIT },
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, LOAD_INIT },
{ display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, NONE },
{ display->atom__KWM_WIN_ICON, META_PROP_VALUE_INVALID, reload_kwm_win_icon, NONE },
{ display->atom__NET_WM_ICON_GEOMETRY, META_PROP_VALUE_CARDINAL_LIST, reload_icon_geometry, LOAD_INIT },
{ display->atom_WM_CLIENT_LEADER, META_PROP_VALUE_INVALID, complain_about_broken_client, NONE },
{ display->atom_SM_CLIENT_ID, META_PROP_VALUE_INVALID, complain_about_broken_client, NONE },
{ display->atom_WM_WINDOW_ROLE, META_PROP_VALUE_STRING, reload_wm_window_role, LOAD_INIT },
{ display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_ATOM_LIST, reload_net_wm_window_type, LOAD_INIT | INCLUDE_OR },
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, NONE },
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, NONE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, NONE },
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, LOAD_INIT | INCLUDE_OR },
MetaWindowPropHooks hooks[] = { /* INIT O-R */
{ display->atom_WM_CLIENT_MACHINE, META_PROP_VALUE_STRING, reload_wm_client_machine, TRUE, TRUE },
{ display->atom__NET_WM_NAME, META_PROP_VALUE_UTF8, reload_net_wm_name, TRUE, TRUE },
{ XA_WM_CLASS, META_PROP_VALUE_CLASS_HINT, reload_wm_class, TRUE, TRUE },
{ display->atom__NET_WM_PID, META_PROP_VALUE_CARDINAL, reload_net_wm_pid, TRUE, TRUE },
{ XA_WM_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name, TRUE, TRUE },
{ display->atom__MUTTER_HINTS, META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, TRUE, TRUE },
{ display->atom__NET_WM_OPAQUE_REGION, META_PROP_VALUE_CARDINAL_LIST, reload_opaque_region, TRUE, TRUE },
{ display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, TRUE, FALSE },
{ display->atom__NET_STARTUP_ID, META_PROP_VALUE_UTF8, reload_net_startup_id, TRUE, FALSE },
{ display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER_LIST, reload_update_counter, TRUE, TRUE },
{ XA_WM_NORMAL_HINTS, META_PROP_VALUE_SIZE_HINTS, reload_normal_hints, TRUE, FALSE },
{ display->atom_WM_PROTOCOLS, META_PROP_VALUE_ATOM_LIST, reload_wm_protocols, TRUE, FALSE },
{ XA_WM_HINTS, META_PROP_VALUE_WM_HINTS, reload_wm_hints, TRUE, FALSE },
{ display->atom__NET_WM_USER_TIME, META_PROP_VALUE_CARDINAL, reload_net_wm_user_time, TRUE, FALSE },
{ display->atom__NET_WM_STATE, META_PROP_VALUE_ATOM_LIST, reload_net_wm_state, TRUE, FALSE },
{ display->atom__MOTIF_WM_HINTS, META_PROP_VALUE_MOTIF_HINTS, reload_mwm_hints, TRUE, FALSE },
{ XA_WM_TRANSIENT_FOR, META_PROP_VALUE_WINDOW, reload_transient_for, TRUE, FALSE },
{ display->atom__GTK_THEME_VARIANT, META_PROP_VALUE_UTF8, reload_gtk_theme_variant, TRUE, FALSE },
{ display->atom__GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED, META_PROP_VALUE_CARDINAL, reload_gtk_hide_titlebar_when_maximized, TRUE, FALSE },
{ display->atom__GTK_APPLICATION_ID, META_PROP_VALUE_UTF8, reload_gtk_application_id, TRUE, FALSE },
{ display->atom__GTK_UNIQUE_BUS_NAME, META_PROP_VALUE_UTF8, reload_gtk_unique_bus_name, TRUE, FALSE },
{ display->atom__GTK_APPLICATION_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_application_object_path, TRUE, FALSE },
{ display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, TRUE, FALSE },
{ display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, TRUE, FALSE },
{ display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, TRUE, FALSE },
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, TRUE, FALSE },
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, TRUE, FALSE },
{ display->atom_WM_STATE, META_PROP_VALUE_INVALID, NULL, FALSE, FALSE },
{ display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, FALSE, FALSE },
{ display->atom__KWM_WIN_ICON, META_PROP_VALUE_INVALID, reload_kwm_win_icon, FALSE, FALSE },
{ display->atom__NET_WM_ICON_GEOMETRY, META_PROP_VALUE_CARDINAL_LIST, reload_icon_geometry, FALSE, FALSE },
{ display->atom_WM_CLIENT_LEADER, META_PROP_VALUE_INVALID, complain_about_broken_client, FALSE, FALSE },
{ display->atom_SM_CLIENT_ID, META_PROP_VALUE_INVALID, complain_about_broken_client, FALSE, FALSE },
{ display->atom_WM_WINDOW_ROLE, META_PROP_VALUE_INVALID, reload_wm_window_role, TRUE, FALSE },
{ display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_INVALID, reload_net_wm_window_type, TRUE, TRUE },
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE },
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, TRUE, TRUE },
{ 0 },
};
@@ -1824,7 +1718,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
while (cursor->property)
{
/* Doing initial loading doesn't make sense if we just want notification */
g_assert (!((cursor->flags & LOAD_INIT) && cursor->type == META_PROP_VALUE_INVALID));
g_assert (!(hooks->load_initially && hooks->type == META_PROP_VALUE_INVALID));
/* Atoms are safe to use with GINT_TO_POINTER because it's safe with
* anything 32 bits or less, and atoms are 32 bits with the top three

View File

@@ -24,7 +24,6 @@
#define META_WINDOW_X11_PRIVATE_H
#include "window-private.h"
#include "x11/iconcache.h"
#include "ui/resizepopup.h"
G_BEGIN_DECLS
@@ -61,10 +60,6 @@ struct _MetaWindowX11Private
/* These are in server coordinates. If we have a frame, it's
* relative to the frame. */
MetaRectangle client_rect;
MetaIconCache icon_cache;
Pixmap wm_hints_pixmap;
Pixmap wm_hints_mask;
};
G_END_DECLS

View File

@@ -503,10 +503,6 @@ static void
meta_window_x11_manage (MetaWindow *window)
{
MetaDisplay *display = window->display;
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
meta_icon_cache_init (&priv->icon_cache);
meta_display_register_x_window (display, &window->xwindow, window);
meta_window_x11_update_shape_region (window);
@@ -522,6 +518,8 @@ meta_window_x11_manage (MetaWindow *window)
if (!window->override_redirect)
update_sm_hints (window); /* must come after transient_for */
meta_window_x11_update_net_wm_type (window);
if (window->decorated)
meta_window_ensure_frame (window);
@@ -548,6 +546,9 @@ meta_window_x11_manage (MetaWindow *window)
if (window->override_redirect)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
}
@@ -1449,25 +1450,6 @@ meta_window_x11_get_default_skip_hints (MetaWindow *window,
*skip_pager_out = priv->wm_state_skip_pager;
}
static gboolean
meta_window_x11_update_icon (MetaWindow *window,
GdkPixbuf **icon,
GdkPixbuf **mini_icon)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
return meta_read_icons (window->screen,
window->xwindow,
&priv->icon_cache,
priv->wm_hints_pixmap,
priv->wm_hints_mask,
icon,
META_ICON_WIDTH, META_ICON_HEIGHT,
mini_icon,
META_MINI_ICON_WIDTH, META_MINI_ICON_HEIGHT);
}
static void
meta_window_x11_class_init (MetaWindowX11Class *klass)
{
@@ -1485,7 +1467,6 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
window_class->move_resize_internal = meta_window_x11_move_resize_internal;
window_class->update_struts = meta_window_x11_update_struts;
window_class->get_default_skip_hints = meta_window_x11_get_default_skip_hints;
window_class->update_icon = meta_window_x11_update_icon;
}
void
@@ -1606,6 +1587,167 @@ meta_window_x11_set_net_wm_state (MetaWindow *window)
}
}
void
meta_window_x11_update_net_wm_type (MetaWindow *window)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
int n_atoms;
Atom *atoms;
int i;
priv->type_atom = None;
n_atoms = 0;
atoms = NULL;
meta_prop_get_atom_list (window->display, window->xwindow,
window->display->atom__NET_WM_WINDOW_TYPE,
&atoms, &n_atoms);
i = 0;
while (i < n_atoms)
{
/* We break as soon as we find one we recognize,
* supposed to prefer those near the front of the list
*/
if (atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DOCK ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_MENU ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG ||
atoms[i] ==
window->display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_TOOLTIP ||
atoms[i] ==
window->display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_COMBO ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DND ||
atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL)
{
priv->type_atom = atoms[i];
break;
}
++i;
}
meta_XFree (atoms);
if (meta_is_verbose ())
{
char *str;
str = NULL;
if (priv->type_atom != None)
{
meta_error_trap_push (window->display);
str = XGetAtomName (window->display->xdisplay, priv->type_atom);
meta_error_trap_pop (window->display);
}
meta_verbose ("Window %s type atom %s\n", window->desc,
str ? str : "(none)");
if (str)
meta_XFree (str);
}
meta_window_x11_recalc_window_type (window);
}
void
meta_window_x11_update_role (MetaWindow *window)
{
char *str;
g_return_if_fail (!window->override_redirect);
if (window->role)
g_free (window->role);
window->role = NULL;
if (meta_prop_get_latin1_string (window->display, window->xwindow,
window->display->atom_WM_WINDOW_ROLE,
&str))
{
window->role = g_strdup (str);
meta_XFree (str);
}
meta_verbose ("Updated role of %s to '%s'\n",
window->desc, window->role ? window->role : "null");
}
static void
meta_window_set_opaque_region (MetaWindow *window,
cairo_region_t *region)
{
g_clear_pointer (&window->opaque_region, cairo_region_destroy);
if (region != NULL)
window->opaque_region = cairo_region_reference (region);
meta_compositor_window_shape_changed (window->display->compositor, window);
}
void
meta_window_x11_update_opaque_region (MetaWindow *window)
{
cairo_region_t *opaque_region = NULL;
gulong *region = NULL;
int nitems;
if (meta_prop_get_cardinal_list (window->display,
window->xwindow,
window->display->atom__NET_WM_OPAQUE_REGION,
&region, &nitems))
{
cairo_rectangle_int_t *rects;
int i, rect_index, nrects;
if (nitems % 4 != 0)
{
meta_verbose ("_NET_WM_OPAQUE_REGION does not have a list of 4-tuples.");
goto out;
}
/* empty region */
if (nitems == 0)
goto out;
nrects = nitems / 4;
rects = g_new (cairo_rectangle_int_t, nrects);
rect_index = 0;
i = 0;
while (i < nitems)
{
cairo_rectangle_int_t *rect = &rects[rect_index];
rect->x = region[i++];
rect->y = region[i++];
rect->width = region[i++];
rect->height = region[i++];
rect_index++;
}
opaque_region = cairo_region_create_rectangles (rects, nrects);
g_free (rects);
}
out:
meta_XFree (region);
meta_window_set_opaque_region (window, opaque_region);
cairo_region_destroy (opaque_region);
}
static cairo_region_t *
region_create_from_x_rectangles (const XRectangle *rects,
int n_rects)
@@ -1628,9 +1770,6 @@ static void
meta_window_set_input_region (MetaWindow *window,
cairo_region_t *region)
{
if (cairo_region_equal (window->input_region, region))
return;
g_clear_pointer (&window->input_region, cairo_region_destroy);
if (region != NULL)
@@ -1737,9 +1876,6 @@ static void
meta_window_set_shape_region (MetaWindow *window,
cairo_region_t *region)
{
if (cairo_region_equal (window->shape_region, region))
return;
g_clear_pointer (&window->shape_region, cairo_region_destroy);
if (region != NULL)
@@ -2797,7 +2933,7 @@ is_our_xwindow (MetaDisplay *display,
if (xwindow == screen->guard_window)
return TRUE;
if (xwindow == screen->composite_overlay_window)
if (xwindow == XCompositeGetOverlayWindow (display->xdisplay, screen->xroot))
return TRUE;
/* Any windows created via meta_create_offscreen_window */
@@ -2929,6 +3065,8 @@ meta_window_x11_new (MetaDisplay *display,
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
meta_core_add_old_event_mask (display->xdisplay, xwindow, &mask);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
@@ -2985,6 +3123,8 @@ meta_window_x11_new (MetaDisplay *display,
meta_display_grab_focus_window_button (window->display, window);
}
meta_window_set_surface_mapped (window, TRUE);
meta_error_trap_pop (display); /* pop the XSync()-reducing trap */
return window;

View File

@@ -55,6 +55,9 @@ void meta_window_x11_destroy_sync_request_alarm (MetaWindow *window);
void meta_window_x11_update_sync_request_counter (MetaWindow *window,
gint64 new_counter_value);
void meta_window_x11_update_role (MetaWindow *window);
void meta_window_x11_update_net_wm_type (MetaWindow *window);
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);