Compare commits
4 Commits
wip/resize
...
wip/surfac
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a3a2109c0c | ||
![]() |
bdbeafc222 | ||
![]() |
89ca36818a | ||
![]() |
fe1a58b459 |
14
NEWS
14
NEWS
@@ -1,17 +1,3 @@
|
||||
3.11.91
|
||||
=======
|
||||
* Don't use keysym to match keybindings [Rui; #678001]
|
||||
* Fix message tray icons showing up blank (again) [Adel; #725180]
|
||||
* Improve keybinding lookups [Rui; #725588]
|
||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
|
||||
* Fix positioning of manually positioned windows [Owen; #724049]
|
||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
|
||||
#724969, #725216, #724402, #722266, #725338, #725525]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.90
|
||||
=======
|
||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
||||
|
@@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [11])
|
||||
m4_define([mutter_micro_version], [91])
|
||||
m4_define([mutter_micro_version], [90])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -78,7 +78,7 @@ MUTTER_PC_MODULES="
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
$CLUTTER_PACKAGE >= 1.17.1
|
||||
cogl-1.0 >= 1.17.1
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
|
@@ -29,18 +29,6 @@
|
||||
<KeyListEntry name="move-to-workspace-down"
|
||||
_description="Move window one workspace down" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-left"
|
||||
_description="Move window one monitor to the left" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-right"
|
||||
_description="Move window one monitor to the right" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-up"
|
||||
_description="Move window one monitor up" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-down"
|
||||
_description="Move window one monitor down" />
|
||||
|
||||
<KeyListEntry name="switch-applications"
|
||||
_description="Switch applications"/>
|
||||
|
||||
|
@@ -6,7 +6,6 @@ lib_LTLIBRARIES = libmutter-wayland.la
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
@@ -113,6 +112,8 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/display.c \
|
||||
core/display-private.h \
|
||||
meta/display.h \
|
||||
ui/draw-workspace.c \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/edid-parse.c \
|
||||
@@ -183,13 +184,14 @@ libmutter_wayland_la_SOURCES = \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
ui/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
ui/tabpopup.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme.c \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
|
@@ -76,7 +76,6 @@
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "util-private.h"
|
||||
#include "frame.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
@@ -953,54 +952,6 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
meta_window_actor_update_surface (window_actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_op_is_clicking (MetaGrabOp grab_op)
|
||||
{
|
||||
switch (grab_op)
|
||||
{
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
case META_GRAB_OP_CLICKING_MENU:
|
||||
case META_GRAB_OP_CLICKING_SHADE:
|
||||
case META_GRAB_OP_CLICKING_UNSHADE:
|
||||
case META_GRAB_OP_CLICKING_ABOVE:
|
||||
case META_GRAB_OP_CLICKING_UNABOVE:
|
||||
case META_GRAB_OP_CLICKING_STICK:
|
||||
case META_GRAB_OP_CLICKING_UNSTICK:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_is_passive_button_grab (MetaDisplay *display,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
/* see display.c for which events are passive button
|
||||
grabs (meta_display_grab_window_buttons() and
|
||||
meta_display_handle_events())
|
||||
we need to filter them here because normally they
|
||||
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
||||
but we want to redirect them to clutter
|
||||
*/
|
||||
|
||||
if (device_event->evtype != XI_ButtonPress)
|
||||
return FALSE;
|
||||
|
||||
if (display->window_grab_modifiers == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
||||
display->window_grab_modifiers)
|
||||
return FALSE;
|
||||
|
||||
return device_event->detail < 4;
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
@@ -1012,7 +963,6 @@ event_is_passive_button_grab (MetaDisplay *display,
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (info->screen);
|
||||
@@ -1021,30 +971,24 @@ maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
event->xcookie.extension == display->xinput_opcode)
|
||||
{
|
||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
||||
let GTK+ handle it without mangling */
|
||||
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
||||
(grab_op_is_clicking (display->grab_op) ||
|
||||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
||||
break;
|
||||
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
||||
* it as-is without mangling. */
|
||||
if (meta_ui_window_is_widget (info->screen->ui, device_event->event))
|
||||
break;
|
||||
|
||||
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1064,12 +1008,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaScreen *screen = display->screens->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
|
||||
{
|
||||
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
|
||||
@@ -1079,13 +1017,43 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
maybe_spoof_event_as_stage_event (info, window, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
if (window)
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
l = meta_display_get_screens (compositor->display);
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaScreen *screen = l->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
maybe_spoof_event_as_stage_event (info, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/screen.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
@@ -577,18 +576,8 @@ static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
|
||||
|
||||
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
|
||||
return NULL;
|
||||
|
||||
while (parent && !META_IS_WINDOW_ACTOR (parent))
|
||||
parent = clutter_actor_get_parent (parent);
|
||||
|
||||
if (parent && clutter_actor_has_mapped_clones (parent))
|
||||
return NULL;
|
||||
|
||||
return priv->unobscured_region;
|
||||
return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
@@ -98,14 +97,6 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
|
||||
return priv->surface->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
{
|
||||
@@ -119,8 +110,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@@ -387,14 +387,6 @@ meta_surface_actor_x11_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_x11_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor));
|
||||
|
||||
return priv->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
{
|
||||
@@ -411,8 +403,6 @@ meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_x11_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -466,7 +456,6 @@ meta_surface_actor_x11_new (MetaWindow *window)
|
||||
priv->unredirected = FALSE;
|
||||
sync_unredirected (self);
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
@@ -311,9 +312,3 @@ meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_surface_actor_get_window (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self);
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -36,8 +35,6 @@ struct _MetaSurfaceActorClass
|
||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||
|
||||
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActor
|
||||
@@ -53,7 +50,6 @@ cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *clip);
|
||||
|
||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
|
||||
|
||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
|
@@ -5,6 +5,9 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <meta-wayland-private.h>
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include "meta-surface-actor.h"
|
||||
|
@@ -28,9 +28,9 @@
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-texture-rectangle.h"
|
||||
#include "region-utils.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "monitor-private.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-x11.h"
|
||||
@@ -1471,7 +1471,6 @@ meta_window_actor_cull_out (MetaCullable *cullable,
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
||||
|
||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||
meta_window_actor_set_clip_region_beneath (self, clip_region);
|
||||
}
|
||||
|
||||
@@ -1714,25 +1713,22 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
||||
if (mask_texture)
|
||||
cogl_object_unref (mask_texture);
|
||||
cogl_object_unref (mask_texture);
|
||||
|
||||
g_free (mask_data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_shape_region (MetaWindowActor *self)
|
||||
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
cairo_region_t *region = NULL;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
|
||||
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
|
||||
{
|
||||
region = cairo_region_copy (priv->window->shape_region);
|
||||
cairo_region_translate (region, client_area.x, client_area.y);
|
||||
cairo_region_translate (region, client_area->x, client_area->y);
|
||||
}
|
||||
else if (priv->window->shape_region != NULL)
|
||||
{
|
||||
@@ -1743,11 +1739,11 @@ meta_window_actor_update_shape_region (MetaWindowActor *self)
|
||||
/* If we don't have a shape on the server, that means that
|
||||
* we have an implicit shape of one rectangle covering the
|
||||
* entire window. */
|
||||
region = cairo_region_create_rectangle (&client_area);
|
||||
region = cairo_region_create_rectangle (client_area);
|
||||
}
|
||||
|
||||
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
|
||||
build_and_scan_frame_mask (self, &client_area, region);
|
||||
build_and_scan_frame_mask (self, client_area, region);
|
||||
|
||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||
priv->shape_region = region;
|
||||
@@ -1758,23 +1754,20 @@ meta_window_actor_update_shape_region (MetaWindowActor *self)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self)
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
cairo_region_t *region = NULL;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
|
||||
if (priv->window->frame != NULL)
|
||||
{
|
||||
region = meta_frame_get_frame_bounds (priv->window->frame);
|
||||
|
||||
/* input_region is in client window coordinates, so translate the
|
||||
/* client area is in client window coordinates, so translate the
|
||||
* input region into that coordinate system and back */
|
||||
cairo_region_translate (region, -client_area.x, -client_area.y);
|
||||
cairo_region_union_rectangle (region, &client_area);
|
||||
cairo_region_translate (region, client_area.x, client_area.y);
|
||||
cairo_region_translate (region, -client_area->x, -client_area->y);
|
||||
cairo_region_union_rectangle (region, client_area);
|
||||
cairo_region_translate (region, client_area->x, client_area->y);
|
||||
}
|
||||
else if (priv->window->shape_region != NULL ||
|
||||
priv->window->input_region != NULL)
|
||||
@@ -1794,7 +1787,7 @@ meta_window_actor_update_input_region (MetaWindowActor *self)
|
||||
/* If we don't have a shape on the server, that means that
|
||||
* we have an implicit shape of one rectangle covering the
|
||||
* entire window. */
|
||||
region = cairo_region_create_rectangle (&client_area);
|
||||
region = cairo_region_create_rectangle (client_area);
|
||||
}
|
||||
|
||||
meta_surface_actor_set_input_region (priv->surface, region);
|
||||
@@ -1810,9 +1803,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
|
||||
if (argb32 && priv->window->opaque_region != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t client_area;
|
||||
MetaFrameBorders borders;
|
||||
|
||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
|
||||
/* The opaque region is defined to be a part of the
|
||||
* window which ARGB32 will always paint with opaque
|
||||
@@ -1825,7 +1818,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
* case, graphical glitches will occur.
|
||||
*/
|
||||
opaque_region = cairo_region_copy (priv->window->opaque_region);
|
||||
cairo_region_translate (opaque_region, client_area.x, client_area.y);
|
||||
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
|
||||
cairo_region_intersect (opaque_region, priv->shape_region);
|
||||
}
|
||||
else if (argb32)
|
||||
@@ -1841,15 +1834,27 @@ static void
|
||||
check_needs_reshape (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaFrameBorders borders;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
if (!priv->needs_reshape)
|
||||
return;
|
||||
|
||||
meta_window_actor_update_shape_region (self);
|
||||
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||
|
||||
client_area.x = borders.total.left;
|
||||
client_area.y = borders.total.top;
|
||||
client_area.width = priv->window->rect.width;
|
||||
if (priv->window->shaded)
|
||||
client_area.height = 0;
|
||||
else
|
||||
client_area.height = priv->window->rect.height;
|
||||
|
||||
meta_window_actor_update_shape_region (self, &client_area);
|
||||
|
||||
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
meta_window_actor_update_input_region (self);
|
||||
meta_window_actor_update_input_region (self, &client_area);
|
||||
meta_window_actor_update_opaque_region (self);
|
||||
}
|
||||
|
||||
|
@@ -491,17 +491,12 @@ place_window_if_needed(MetaWindow *window,
|
||||
!window->minimized &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
MetaRectangle orig_rect;
|
||||
MetaRectangle placed_rect;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
|
||||
meta_window_get_frame_rect (window, &placed_rect);
|
||||
|
||||
orig_rect = info->orig;
|
||||
extend_by_frame (window, &orig_rect);
|
||||
|
||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
||||
meta_window_place (window, info->orig.x, info->orig.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
|
@@ -215,6 +215,7 @@ struct _MetaDisplay
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
@@ -232,8 +233,8 @@ struct _MetaDisplay
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
/* Keybindings stuff */
|
||||
GHashTable *key_bindings;
|
||||
GHashTable *key_bindings_index;
|
||||
MetaKeyBinding *key_bindings;
|
||||
int n_key_bindings;
|
||||
int min_keycode;
|
||||
int max_keycode;
|
||||
KeySym *keymap;
|
||||
|
@@ -75,6 +75,14 @@
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
|
||||
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
|
||||
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
|
||||
g == META_GRAB_OP_KEYBOARD_TABBING_GROUP || \
|
||||
g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \
|
||||
g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \
|
||||
g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP)
|
||||
|
||||
/*
|
||||
* SECTION:pings
|
||||
*
|
||||
@@ -1367,6 +1375,13 @@ grab_op_is_keyboard (MetaGrabOp op)
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING_GROUP:
|
||||
case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL:
|
||||
case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK:
|
||||
case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP:
|
||||
case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING:
|
||||
case META_GRAB_OP_COMPOSITOR:
|
||||
return TRUE;
|
||||
|
||||
@@ -1667,19 +1682,13 @@ get_window_for_event (MetaDisplay *display,
|
||||
if (display->grab_op != META_GRAB_OP_NONE)
|
||||
return display->grab_window;
|
||||
|
||||
/* Always use the key focused window for key events. */
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
return display->focus_window;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
if (META_IS_SURFACE_ACTOR (source))
|
||||
return meta_surface_actor_get_window (META_SURFACE_ACTOR (source));
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (source))
|
||||
{
|
||||
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (source));
|
||||
g_assert (surface != NULL);
|
||||
return surface->window;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1776,9 +1785,19 @@ update_focus_window (MetaDisplay *display,
|
||||
|
||||
if (display->focus_window)
|
||||
{
|
||||
ClutterActor *window_actor;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
|
||||
display->focus_window->desc, serial);
|
||||
meta_window_set_focused_internal (display->focus_window, TRUE);
|
||||
|
||||
/* XXX -- this is sort of a layer violation, but because we
|
||||
* rely on the compositor for event delivery anyway, I don't
|
||||
* think it's too bad... */
|
||||
|
||||
window_actor = CLUTTER_ACTOR (display->focus_window->compositor_private);
|
||||
if (window_actor)
|
||||
clutter_actor_grab_key_focus (window_actor);
|
||||
}
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
|
||||
@@ -2021,6 +2040,9 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
gboolean bypass_clutter = FALSE, bypass_wayland = FALSE;
|
||||
MetaWaylandCompositor *compositor = NULL;
|
||||
|
||||
/* XXX -- we need to fill this in properly at some point... */
|
||||
gboolean frame_was_receiver = FALSE;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
@@ -2072,76 +2094,79 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
(display->grab_window ?
|
||||
display->grab_window->desc :
|
||||
"none"));
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Syncing to old stack positions.\n");
|
||||
|
||||
/* XXX: I'm not sure if this is the right thing to do.
|
||||
The pre-Wayland code was only calling
|
||||
meta_stack_set_positions if the modified window was a
|
||||
root window */
|
||||
if (event->any.source == CLUTTER_ACTOR (event->any.stage) && window && window->screen)
|
||||
meta_stack_set_positions (window->screen->stack,
|
||||
display->grab_old_window_stacking);
|
||||
}
|
||||
meta_display_end_grab_op (display, event->any.time);
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
gboolean begin_move = FALSE;
|
||||
ClutterModifierType grab_mask;
|
||||
gboolean unmodified;
|
||||
gboolean fully_modified;
|
||||
|
||||
grab_mask = display->window_grab_modifiers;
|
||||
if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
|
||||
grab_mask |= CLUTTER_CONTROL_MASK;
|
||||
|
||||
/* We have three passive button grabs:
|
||||
* - on any button, without modifiers => focuses and maybe raises the window
|
||||
* - on resize button, with modifiers => start an interactive resizing
|
||||
* (normally <Super>middle)
|
||||
* - on move button, with modifiers => start an interactive move
|
||||
* (normally <Super>left)
|
||||
* - on menu button, with modifiers => show the window menu
|
||||
* (normally <Super>right)
|
||||
*
|
||||
* We may get here because we actually have a button
|
||||
* grab on the window, or because we're a wayland
|
||||
* compositor and thus we see all the events, so we
|
||||
* need to check if the event is interesting.
|
||||
* We want an event that is not modified, for a window
|
||||
* that has (or would have, the wayland case) the
|
||||
* button grab active.
|
||||
*
|
||||
* We may have other events on the window, for example
|
||||
* a click on a frame button, but that's not for us to
|
||||
* care about. Just let the event through.
|
||||
/* Two possible sources of an unmodified event; one is a
|
||||
* client that's letting button presses pass through to the
|
||||
* frame, the other is our focus_window_grab on unmodified
|
||||
* button 1. So for all such events we focus the window.
|
||||
*/
|
||||
unmodified = (event->button.modifier_state & grab_mask) == 0;
|
||||
fully_modified = grab_mask && (event->button.modifier_state & grab_mask) == grab_mask;
|
||||
|
||||
if (unmodified && window && window->have_focus_click_grab)
|
||||
if (unmodified ||
|
||||
event->button.button == 1)
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Not raising window on click due to don't-raise-on-click option\n");
|
||||
|
||||
/* Don't focus panels--they must explicitly request focus.
|
||||
* See bug 160470
|
||||
/* don't focus if frame received, will be lowered in
|
||||
* frames.c or special-cased if the click was on a
|
||||
* minimize/close button.
|
||||
*/
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
if (!frame_was_receiver)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s due to unmodified button %u press (display.c)\n",
|
||||
window->desc, event->button.button);
|
||||
meta_window_focus (window, event->any.time);
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Not raising window on click due to don't-raise-on-click option\n");
|
||||
|
||||
/* Don't focus panels--they must explicitly request focus.
|
||||
* See bug 160470
|
||||
*/
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s due to unmodified button %u press (display.c)\n",
|
||||
window->desc, event->button.button);
|
||||
meta_window_focus (window, event->any.time);
|
||||
}
|
||||
else
|
||||
/* However, do allow terminals to lose focus due to new
|
||||
* window mappings after the user clicks on a panel.
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
}
|
||||
else
|
||||
/* However, do allow terminals to lose focus due to new
|
||||
* window mappings after the user clicks on a panel.
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
|
||||
meta_verbose ("Allowing events time %u\n",
|
||||
(unsigned int)event->button.time);
|
||||
|
||||
XIAllowEvents (display->xdisplay, clutter_input_device_get_device_id (event->button.device),
|
||||
XIReplayDevice, event->button.time);
|
||||
bypass_clutter = TRUE;
|
||||
/* you can move on alt-click but not on
|
||||
* the click-to-focus
|
||||
*/
|
||||
if (!unmodified)
|
||||
begin_move = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ())
|
||||
else if (!unmodified && ((int) event->button.button == meta_prefs_get_mouse_button_resize ()))
|
||||
{
|
||||
if (window->has_resize_func)
|
||||
{
|
||||
@@ -2189,10 +2214,8 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||
else if ((int) event->button.button == meta_prefs_get_mouse_button_menu ())
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
@@ -2204,22 +2227,20 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == 1)
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
{
|
||||
if (window->has_move_func)
|
||||
{
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
FALSE,
|
||||
event->button.button,
|
||||
0,
|
||||
event->any.time,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
}
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
FALSE,
|
||||
event->button.button,
|
||||
0,
|
||||
event->any.time,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
@@ -2288,10 +2309,11 @@ handle_input_xevent (MetaDisplay *display,
|
||||
XIEvent *input_event,
|
||||
gulong serial)
|
||||
{
|
||||
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
|
||||
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
||||
Window modified;
|
||||
MetaWindow *window;
|
||||
MetaScreen *screen;
|
||||
gboolean frame_was_receiver;
|
||||
|
||||
if (input_event == NULL)
|
||||
return FALSE;
|
||||
@@ -2299,8 +2321,242 @@ handle_input_xevent (MetaDisplay *display,
|
||||
modified = xievent_get_modified_window (display, input_event);
|
||||
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
|
||||
|
||||
frame_was_receiver = FALSE;
|
||||
if (window &&
|
||||
window->frame &&
|
||||
modified == window->frame->xwindow)
|
||||
{
|
||||
/* Note that if the frame and the client both have an
|
||||
* XGrabButton (as is normal with our setup), the event
|
||||
* goes to the frame.
|
||||
*/
|
||||
frame_was_receiver = TRUE;
|
||||
meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
|
||||
window->desc);
|
||||
}
|
||||
|
||||
if (window && !window->override_redirect &&
|
||||
(input_event->evtype == XI_KeyPress || input_event->evtype == XI_ButtonPress))
|
||||
{
|
||||
if (CurrentTime == display->current_time)
|
||||
{
|
||||
/* We can't use missing (i.e. invalid) timestamps to set user time,
|
||||
* nor do we want to use them to sanity check other timestamps.
|
||||
* See bug 313490 for more details.
|
||||
*/
|
||||
meta_warning ("Event has no timestamp! You may be using a broken "
|
||||
"program such as xse. Please ask the authors of that "
|
||||
"program to fix it.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_set_user_time (window, display->current_time);
|
||||
sanity_check_timestamps (display, display->current_time);
|
||||
}
|
||||
}
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_ButtonPress:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
|
||||
if (device_event->detail == 4 || device_event->detail == 5)
|
||||
/* Scrollwheel event, do nothing and deliver event to compositor below */
|
||||
break;
|
||||
|
||||
if ((window &&
|
||||
meta_grab_op_is_mouse (display->grab_op) &&
|
||||
(device_event->mods.effective & display->window_grab_modifiers) &&
|
||||
display->grab_button != device_event->detail &&
|
||||
display->grab_window == window) ||
|
||||
grab_op_is_keyboard (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ending grab op %u on window %s due to button press\n",
|
||||
display->grab_op,
|
||||
(display->grab_window ?
|
||||
display->grab_window->desc :
|
||||
"none"));
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
MetaScreen *screen;
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Syncing to old stack positions.\n");
|
||||
screen =
|
||||
meta_display_screen_for_root (display, device_event->event);
|
||||
|
||||
if (screen!=NULL)
|
||||
meta_stack_set_positions (screen->stack,
|
||||
display->grab_old_window_stacking);
|
||||
}
|
||||
meta_display_end_grab_op (display,
|
||||
device_event->time);
|
||||
}
|
||||
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
gboolean begin_move = FALSE;
|
||||
unsigned int grab_mask;
|
||||
gboolean unmodified;
|
||||
|
||||
grab_mask = display->window_grab_modifiers;
|
||||
if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
|
||||
grab_mask |= ControlMask;
|
||||
|
||||
/* Two possible sources of an unmodified event; one is a
|
||||
* client that's letting button presses pass through to the
|
||||
* frame, the other is our focus_window_grab on unmodified
|
||||
* button 1. So for all such events we focus the window.
|
||||
*/
|
||||
unmodified = (device_event->mods.effective & grab_mask) == 0;
|
||||
|
||||
if (unmodified ||
|
||||
device_event->detail == 1)
|
||||
{
|
||||
/* don't focus if frame received, will be lowered in
|
||||
* frames.c or special-cased if the click was on a
|
||||
* minimize/close button.
|
||||
*/
|
||||
if (!frame_was_receiver)
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Not raising window on click due to don't-raise-on-click option\n");
|
||||
|
||||
/* Don't focus panels--they must explicitly request focus.
|
||||
* See bug 160470
|
||||
*/
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s due to unmodified button %u press (display.c)\n",
|
||||
window->desc, device_event->detail);
|
||||
meta_window_focus (window, device_event->time);
|
||||
}
|
||||
else
|
||||
/* However, do allow terminals to lose focus due to new
|
||||
* window mappings after the user clicks on a panel.
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
}
|
||||
|
||||
/* you can move on alt-click but not on
|
||||
* the click-to-focus
|
||||
*/
|
||||
if (!unmodified)
|
||||
begin_move = TRUE;
|
||||
}
|
||||
else if (!unmodified && device_event->detail == meta_prefs_get_mouse_button_resize())
|
||||
{
|
||||
if (window->has_resize_func)
|
||||
{
|
||||
gboolean north, south;
|
||||
gboolean west, east;
|
||||
MetaRectangle frame_rect;
|
||||
MetaGrabOp op;
|
||||
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
west = device_event->root_x < (frame_rect.x + 1 * frame_rect.width / 3);
|
||||
east = device_event->root_x > (frame_rect.x + 2 * frame_rect.width / 3);
|
||||
north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
|
||||
south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
|
||||
|
||||
if (north && west)
|
||||
op = META_GRAB_OP_RESIZING_NW;
|
||||
else if (north && east)
|
||||
op = META_GRAB_OP_RESIZING_NE;
|
||||
else if (south && west)
|
||||
op = META_GRAB_OP_RESIZING_SW;
|
||||
else if (south && east)
|
||||
op = META_GRAB_OP_RESIZING_SE;
|
||||
else if (north)
|
||||
op = META_GRAB_OP_RESIZING_N;
|
||||
else if (west)
|
||||
op = META_GRAB_OP_RESIZING_W;
|
||||
else if (east)
|
||||
op = META_GRAB_OP_RESIZING_E;
|
||||
else if (south)
|
||||
op = META_GRAB_OP_RESIZING_S;
|
||||
else /* Middle region is no-op to avoid user triggering wrong action */
|
||||
op = META_GRAB_OP_NONE;
|
||||
|
||||
if (op != META_GRAB_OP_NONE)
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
op,
|
||||
TRUE,
|
||||
FALSE,
|
||||
device_event->detail,
|
||||
0,
|
||||
device_event->time,
|
||||
device_event->root_x,
|
||||
device_event->root_y);
|
||||
}
|
||||
}
|
||||
else if (device_event->detail == meta_prefs_get_mouse_button_menu())
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
meta_window_show_menu (window,
|
||||
device_event->root_x,
|
||||
device_event->root_y,
|
||||
device_event->detail,
|
||||
device_event->time);
|
||||
}
|
||||
|
||||
if (!frame_was_receiver && unmodified)
|
||||
{
|
||||
/* This is from our synchronous grab since
|
||||
* it has no modifiers and was on the client window
|
||||
*/
|
||||
|
||||
meta_verbose ("Allowing events time %u\n",
|
||||
(unsigned int)device_event->time);
|
||||
|
||||
XIAllowEvents (display->xdisplay, device_event->deviceid,
|
||||
XIReplayDevice, device_event->time);
|
||||
}
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
{
|
||||
meta_display_begin_grab_op (display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
FALSE,
|
||||
device_event->detail,
|
||||
0,
|
||||
device_event->time,
|
||||
device_event->root_x,
|
||||
device_event->root_y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_mouse (display->grab_op))
|
||||
meta_window_handle_mouse_grab_op_xevent (window, device_event);
|
||||
break;
|
||||
case XI_Motion:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_mouse (display->grab_op))
|
||||
meta_window_handle_mouse_grab_op_xevent (window, device_event);
|
||||
break;
|
||||
case XI_Enter:
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
break;
|
||||
@@ -2356,11 +2612,12 @@ handle_input_xevent (MetaDisplay *display,
|
||||
if (!window)
|
||||
{
|
||||
/* Check if the window is a root window. */
|
||||
if (enter_event->root != enter_event->event)
|
||||
MetaScreen *screen =
|
||||
meta_display_screen_for_root(display,
|
||||
enter_event->event);
|
||||
if (screen == NULL)
|
||||
break;
|
||||
|
||||
screen = meta_display_screen_for_root (display, enter_event->root);
|
||||
|
||||
if (enter_event->evtype == XI_FocusIn &&
|
||||
enter_event->mode == XINotifyDetailNone)
|
||||
{
|
||||
@@ -2386,9 +2643,7 @@ handle_input_xevent (MetaDisplay *display,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Don't send FocusIn / FocusOut to Clutter */
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -3382,10 +3637,26 @@ meta_spew_xi2_event (MetaDisplay *display,
|
||||
const char *name = NULL;
|
||||
char *extra = NULL;
|
||||
|
||||
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
|
||||
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
name = "XI_Motion";
|
||||
break;
|
||||
case XI_ButtonPress:
|
||||
name = "XI_ButtonPress";
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
name = "XI_ButtonRelease";
|
||||
break;
|
||||
case XI_KeyPress:
|
||||
name = "XI_KeyPress";
|
||||
break;
|
||||
case XI_KeyRelease:
|
||||
name = "XI_KeyRelease";
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
name = "XI_FocusIn";
|
||||
break;
|
||||
@@ -3410,6 +3681,34 @@ meta_spew_xi2_event (MetaDisplay *display,
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
extra = g_strdup_printf ("win: 0x%lx x: %g y: %g",
|
||||
device_event->event,
|
||||
device_event->root_x,
|
||||
device_event->root_y);
|
||||
break;
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
extra = g_strdup_printf ("button %u x %g y %g root 0x%lx",
|
||||
device_event->detail,
|
||||
device_event->root_x,
|
||||
device_event->root_y,
|
||||
device_event->root);
|
||||
break;
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
KeySym keysym;
|
||||
const char *str;
|
||||
|
||||
keysym = XKeycodeToKeysym (display->xdisplay, device_event->detail, 0);
|
||||
|
||||
str = XKeysymToString (keysym);
|
||||
|
||||
extra = g_strdup_printf ("Key '%s' state 0x%x",
|
||||
str ? str : "none", device_event->mods.effective);
|
||||
}
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
extra = g_strdup_printf ("detail: %s mode: %s\n",
|
||||
@@ -4037,6 +4336,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
display->grab_latest_motion_y = root_y;
|
||||
display->grab_last_moveresize_time.tv_sec = 0;
|
||||
display->grab_last_moveresize_time.tv_usec = 0;
|
||||
display->grab_motion_notify_time = 0;
|
||||
display->grab_old_window_stacking = NULL;
|
||||
#ifdef HAVE_XSYNC
|
||||
display->grab_last_user_action_was_snap = FALSE;
|
||||
@@ -4073,6 +4373,16 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
|
||||
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
||||
|
||||
/* Save the old stacking */
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Saving old stack positions; old pointer was %p.\n",
|
||||
display->grab_old_window_stacking);
|
||||
display->grab_old_window_stacking =
|
||||
meta_stack_get_positions (screen->stack);
|
||||
}
|
||||
|
||||
if (display->grab_window)
|
||||
{
|
||||
meta_window_refresh_resize_popup (display->grab_window);
|
||||
@@ -4114,6 +4424,20 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
if (!display->grab_threshold_movement_reached)
|
||||
meta_window_raise (display->grab_window);
|
||||
}
|
||||
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) ||
|
||||
display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING)
|
||||
{
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
meta_screen_tab_popup_destroy (display->grab_screen);
|
||||
else
|
||||
meta_screen_workspace_popup_destroy (display->grab_screen);
|
||||
|
||||
/* If the ungrab here causes an EnterNotify, ignore it for
|
||||
* sloppy focus
|
||||
*/
|
||||
display->ungrab_should_not_cause_focus_window = display->grab_xwindow;
|
||||
}
|
||||
|
||||
/* If this was a move or resize clear out the edge cache */
|
||||
if (meta_grab_op_is_resizing (display->grab_op) ||
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#include <gio/gio.h>
|
||||
#include <meta/keybindings.h>
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
struct _MetaKeyHandler
|
||||
{
|
||||
char *name;
|
||||
@@ -48,48 +47,9 @@ struct _MetaKeyBinding
|
||||
KeyCode keycode;
|
||||
unsigned int mask;
|
||||
MetaVirtualModifier modifiers;
|
||||
gint flags;
|
||||
MetaKeyHandler *handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *combos;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
void meta_display_init_keys (MetaDisplay *display);
|
||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
@@ -117,8 +77,5 @@ gboolean meta_prefs_add_keybinding (const char *name,
|
||||
|
||||
gboolean meta_prefs_remove_keybinding (const char *name);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
|
||||
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
|
||||
|
||||
#include <config.h>
|
||||
#include <meta/main.h>
|
||||
@@ -53,7 +53,7 @@
|
||||
#include "session.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib-unix.h>
|
||||
|
@@ -1074,13 +1074,12 @@ get_pointer_position_gdk (int *x,
|
||||
GdkScreen *gscreen;
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
gdevice = gdk_device_manager_get_client_pointer (gmanager);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1096,12 +1095,9 @@ get_pointer_position_clutter (int *x,
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
*x = point.x;
|
||||
*y = point.y;
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -650,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
break;
|
||||
case META_POWER_SAVE_OFF:
|
||||
state = DRM_MODE_DPMS_OFF;
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "util-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "monitor-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
|
||||
|
@@ -57,6 +57,7 @@
|
||||
|
||||
#define KEY_OVERLAY_KEY "overlay-key"
|
||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
||||
#define KEY_NO_TAB_POPUP "no-tab-popup"
|
||||
|
||||
/* These are the different schemas we are keeping
|
||||
* a GSettings instance for */
|
||||
@@ -111,6 +112,8 @@ static char **workspace_names = NULL;
|
||||
|
||||
static gboolean workspaces_only_on_primary = FALSE;
|
||||
|
||||
static gboolean no_tab_popup = FALSE;
|
||||
|
||||
static char *iso_next_group_option = NULL;
|
||||
|
||||
static void handle_preference_update_enum (GSettings *settings,
|
||||
@@ -362,6 +365,13 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&workspaces_only_on_primary,
|
||||
},
|
||||
{
|
||||
{ KEY_NO_TAB_POPUP,
|
||||
SCHEMA_MUTTER,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
},
|
||||
&no_tab_popup,
|
||||
},
|
||||
{
|
||||
{ "auto-maximize",
|
||||
SCHEMA_MUTTER,
|
||||
@@ -1803,6 +1813,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
|
||||
return "WORKSPACES_ONLY_ON_PRIMARY";
|
||||
|
||||
case META_PREF_NO_TAB_POPUP:
|
||||
return "NO_TAB_POPUP";
|
||||
|
||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||
return "DRAGGABLE_BORDER_WIDTH";
|
||||
|
||||
@@ -1856,7 +1869,7 @@ init_bindings (void)
|
||||
pref = g_new0 (MetaKeyPref, 1);
|
||||
pref->name = g_strdup ("overlay-key");
|
||||
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
|
||||
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
|
||||
pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
|
||||
pref->builtin = 1;
|
||||
|
||||
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
|
||||
@@ -1866,7 +1879,7 @@ static gboolean
|
||||
update_binding (MetaKeyPref *binding,
|
||||
gchar **strokes)
|
||||
{
|
||||
GSList *old_combos, *a, *b;
|
||||
GSList *old_bindings, *a, *b;
|
||||
gboolean changed;
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
@@ -1878,8 +1891,8 @@ update_binding (MetaKeyPref *binding,
|
||||
"Binding \"%s\" has new GSettings value\n",
|
||||
binding->name);
|
||||
|
||||
old_combos = binding->combos;
|
||||
binding->combos = NULL;
|
||||
old_bindings = binding->bindings;
|
||||
binding->bindings = NULL;
|
||||
|
||||
for (i = 0; strokes && strokes[i]; i++)
|
||||
{
|
||||
@@ -1920,17 +1933,17 @@ update_binding (MetaKeyPref *binding,
|
||||
combo->keysym = keysym;
|
||||
combo->keycode = keycode;
|
||||
combo->modifiers = mods;
|
||||
binding->combos = g_slist_prepend (binding->combos, combo);
|
||||
binding->bindings = g_slist_prepend (binding->bindings, combo);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
||||
binding->name, keysym, keycode, mods);
|
||||
}
|
||||
|
||||
binding->combos = g_slist_reverse (binding->combos);
|
||||
binding->bindings = g_slist_reverse (binding->bindings);
|
||||
|
||||
a = old_combos;
|
||||
b = binding->combos;
|
||||
a = old_bindings;
|
||||
b = binding->bindings;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((!a && b) || (a && !b))
|
||||
@@ -1955,7 +1968,7 @@ update_binding (MetaKeyPref *binding,
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free_full (old_combos, g_free);
|
||||
g_slist_free_full (old_bindings, g_free);
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -2090,7 +2103,7 @@ meta_prefs_add_keybinding (const char *name,
|
||||
pref->name = g_strdup (name);
|
||||
pref->settings = g_object_ref (settings);
|
||||
pref->action = action;
|
||||
pref->combos = NULL;
|
||||
pref->bindings = NULL;
|
||||
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
||||
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
||||
@@ -2154,6 +2167,11 @@ meta_prefs_remove_keybinding (const char *name)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_get_keybindings:
|
||||
*
|
||||
* Returns: (element-type MetaKeyPref) (transfer container):
|
||||
*/
|
||||
GList *
|
||||
meta_prefs_get_keybindings ()
|
||||
{
|
||||
@@ -2254,7 +2272,7 @@ meta_prefs_get_window_binding (const char *name,
|
||||
|
||||
if (pref->per_window)
|
||||
{
|
||||
GSList *s = pref->combos;
|
||||
GSList *s = pref->bindings;
|
||||
|
||||
while (s)
|
||||
{
|
||||
@@ -2302,6 +2320,25 @@ meta_prefs_get_workspaces_only_on_primary (void)
|
||||
return workspaces_only_on_primary;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_no_tab_popup (void)
|
||||
{
|
||||
return no_tab_popup;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_no_tab_popup (gboolean whether)
|
||||
{
|
||||
MetaBasePreference *pref;
|
||||
|
||||
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
|
||||
KEY_NO_TAB_POPUP, &pref))
|
||||
{
|
||||
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
meta_prefs_get_draggable_border_width (void)
|
||||
{
|
||||
|
@@ -64,6 +64,7 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
|
||||
guint tile_preview_timeout_id;
|
||||
|
||||
@@ -149,6 +150,22 @@ void meta_screen_foreach_window (MetaScreen *scree
|
||||
|
||||
void meta_screen_update_cursor (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_window);
|
||||
void meta_screen_tab_popup_forward (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_backward (MetaScreen *screen);
|
||||
MetaWindow* meta_screen_tab_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection);
|
||||
void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace);
|
||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
gboolean delay);
|
||||
void meta_screen_hide_tile_preview (MetaScreen *screen);
|
||||
|
@@ -43,7 +43,7 @@
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "core.h"
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
@@ -308,8 +308,6 @@ set_supported_hint (MetaScreen *screen)
|
||||
#include <meta/atomnames.h>
|
||||
#undef item
|
||||
#undef EWMH_ATOMS_ONLY
|
||||
|
||||
screen->display->atom__GTK_FRAME_EXTENTS,
|
||||
};
|
||||
|
||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||
@@ -762,6 +760,9 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
|
||||
screen->tab_popup = NULL;
|
||||
screen->ws_popup = NULL;
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
screen->stack = meta_stack_new (screen);
|
||||
@@ -1427,6 +1428,253 @@ meta_screen_update_cursor (MetaScreen *screen)
|
||||
screen->current_cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
GList *tab_list;
|
||||
GList *tmp;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (screen->tab_popup)
|
||||
return;
|
||||
|
||||
tab_list = meta_display_get_tab_list (screen->display,
|
||||
list_type,
|
||||
screen,
|
||||
screen->active_workspace);
|
||||
|
||||
len = g_list_length (tab_list);
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
tmp = tab_list;
|
||||
while (i < len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaRectangle r;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) window;
|
||||
entries[i].title = window->title;
|
||||
entries[i].icon = g_object_ref (window->icon);
|
||||
entries[i].blank = FALSE;
|
||||
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entries[i].demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||
!entries[i].hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_frame_rect (window, &r);
|
||||
|
||||
entries[i].rect = r;
|
||||
|
||||
/* Find inside of highlight rectangle to be used when window is
|
||||
* outlined for tabbing. This should be the size of the
|
||||
* east/west frame, and the size of the south frame, on those
|
||||
* sides. On the top it should be the size of the south frame
|
||||
* edge.
|
||||
*/
|
||||
#define OUTLINE_WIDTH 5
|
||||
/* Top side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height > 0 &&
|
||||
window->frame->child_y >= window->frame->bottom_height)
|
||||
entries[i].inner_rect.y = window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.y = OUTLINE_WIDTH;
|
||||
|
||||
/* Bottom side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height != 0)
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - OUTLINE_WIDTH;
|
||||
|
||||
/* Left side */
|
||||
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
|
||||
entries[i].inner_rect.x = window->frame->child_x;
|
||||
else
|
||||
entries[i].inner_rect.x = OUTLINE_WIDTH;
|
||||
|
||||
/* Right side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->right_width != 0)
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - window->frame->right_width;
|
||||
else
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - OUTLINE_WIDTH;
|
||||
|
||||
++i;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (!meta_prefs_get_no_tab_popup ())
|
||||
screen->tab_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
5, /* FIXME */
|
||||
TRUE);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
g_object_unref (entries[i].icon);
|
||||
|
||||
g_free (entries);
|
||||
|
||||
g_list_free (tab_list);
|
||||
|
||||
meta_ui_tab_popup_select (screen->tab_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
|
||||
if (show_type != META_TAB_SHOW_INSTANTLY)
|
||||
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_forward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_forward (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_backward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_backward (screen->tab_popup);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_screen_tab_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
|
||||
|
||||
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (screen->tab_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->tab_popup);
|
||||
screen->tab_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
int len;
|
||||
int i;
|
||||
MetaWorkspaceLayout layout;
|
||||
int n_workspaces;
|
||||
int current_workspace;
|
||||
|
||||
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
|
||||
return;
|
||||
|
||||
current_workspace = meta_workspace_index (screen->active_workspace);
|
||||
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||
|
||||
meta_screen_calc_workspace_layout (screen, n_workspaces,
|
||||
current_workspace, &layout);
|
||||
|
||||
len = layout.grid_area;
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
if (layout.grid[i] >= 0)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
workspace = meta_screen_get_workspace_by_index (screen,
|
||||
layout.grid[i]);
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) workspace;
|
||||
entries[i].title = meta_workspace_get_name (workspace);
|
||||
entries[i].icon = NULL;
|
||||
entries[i].blank = FALSE;
|
||||
|
||||
g_assert (entries[i].title != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
entries[i].key = NULL;
|
||||
entries[i].title = NULL;
|
||||
entries[i].icon = NULL;
|
||||
entries[i].blank = TRUE;
|
||||
}
|
||||
entries[i].hidden = FALSE;
|
||||
entries[i].demands_attention = FALSE;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
screen->ws_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
layout.cols,
|
||||
FALSE);
|
||||
|
||||
g_free (entries);
|
||||
meta_screen_free_workspace_layout (&layout);
|
||||
|
||||
meta_ui_tab_popup_select (screen->ws_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
g_return_if_fail (screen->ws_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_select (screen->ws_popup,
|
||||
(MetaTabEntryKey) workspace);
|
||||
}
|
||||
|
||||
MetaWorkspace *
|
||||
meta_screen_workspace_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->ws_popup != NULL, NULL);
|
||||
|
||||
return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (screen->ws_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->ws_popup);
|
||||
screen->ws_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_update_tile_preview_timeout (gpointer data)
|
||||
{
|
||||
@@ -1514,19 +1762,38 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one)
|
||||
{
|
||||
MetaWindow *window;
|
||||
int x, y;
|
||||
Window root_return, child_return;
|
||||
double root_x_return, root_y_return;
|
||||
double win_x_return, win_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_error_trap_push (screen->display);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
meta_error_trap_pop (screen->display);
|
||||
free (buttons.mask);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
not_this_one,
|
||||
x, y);
|
||||
root_x_return,
|
||||
root_y_return);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -1808,11 +2075,28 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
int x, y;
|
||||
Window root_return, child_return;
|
||||
double win_x_return, win_y_return;
|
||||
double root_x_return, root_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_screen_get_current_monitor_for_pos (screen, x, y);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
free (buttons.mask);
|
||||
|
||||
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
|
@@ -408,6 +408,12 @@ struct _MetaWindow
|
||||
*/
|
||||
MetaRectangle rect;
|
||||
|
||||
/* The size and position we want the window to be (i.e. what we last asked
|
||||
* the client to configure).
|
||||
* This is only used for wayland clients.
|
||||
*/
|
||||
MetaRectangle expected_rect;
|
||||
|
||||
gboolean has_custom_frame_extents;
|
||||
GtkBorder custom_frame_extents;
|
||||
|
||||
@@ -737,9 +743,6 @@ void meta_window_set_surface_mapped (MetaWindow *window,
|
||||
|
||||
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
|
||||
|
||||
void meta_window_get_client_area_rect (const MetaWindow *window,
|
||||
cairo_rectangle_int_t *rect);
|
||||
|
||||
void meta_window_activate_full (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaClientType source_indication,
|
||||
|
@@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _XOPEN_SOURCE 500 /* for gethostname() */
|
||||
#define _SVID_SOURCE /* for gethostname() */
|
||||
|
||||
#include <config.h>
|
||||
#include "window-props.h"
|
||||
|
@@ -38,7 +38,6 @@
|
||||
#include <meta/common.h>
|
||||
#include <meta/errors.h>
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "window-private.h"
|
||||
#include "window-props.h"
|
||||
@@ -396,7 +395,6 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
XRectangle *rects = NULL;
|
||||
int n_rects, ordering;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
ShapeInput,
|
||||
@@ -674,19 +672,35 @@ meta_window_x11_property_notify (MetaWindow *window,
|
||||
static int
|
||||
query_pressed_buttons (MetaWindow *window)
|
||||
{
|
||||
ClutterModifierType mods;
|
||||
double x, y, query_root_x, query_root_y;
|
||||
Window root, child;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int button = 0;
|
||||
|
||||
meta_cursor_tracker_get_pointer (window->screen->cursor_tracker,
|
||||
NULL, NULL, &mods);
|
||||
meta_error_trap_push (window->display);
|
||||
XIQueryPointer (window->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
window->xwindow,
|
||||
&root, &child,
|
||||
&query_root_x, &query_root_y,
|
||||
&x, &y,
|
||||
&buttons, &mods, &group);
|
||||
|
||||
if (mods & CLUTTER_BUTTON1_MASK)
|
||||
if (meta_error_trap_pop_with_return (window->display) != Success)
|
||||
goto out;
|
||||
|
||||
if (XIMaskIsSet (buttons.mask, Button1))
|
||||
button |= 1 << 1;
|
||||
if (mods & CLUTTER_BUTTON2_MASK)
|
||||
if (XIMaskIsSet (buttons.mask, Button2))
|
||||
button |= 1 << 2;
|
||||
if (mods & CLUTTER_BUTTON3_MASK)
|
||||
if (XIMaskIsSet (buttons.mask, Button3))
|
||||
button |= 1 << 3;
|
||||
|
||||
free (buttons.mask);
|
||||
|
||||
out:
|
||||
return button;
|
||||
}
|
||||
|
||||
|
@@ -86,9 +86,8 @@ static void meta_window_show (MetaWindow *window);
|
||||
static void meta_window_hide (MetaWindow *window);
|
||||
|
||||
static void meta_window_save_rect (MetaWindow *window);
|
||||
static void save_user_window_placement (MetaWindow *window,
|
||||
MetaRectangle *rect,
|
||||
gboolean force);
|
||||
static void save_user_window_placement (MetaWindow *window);
|
||||
static void force_save_user_window_placement (MetaWindow *window);
|
||||
|
||||
static void meta_window_move_resize_internal (MetaWindow *window,
|
||||
MetaMoveResizeFlags flags,
|
||||
@@ -994,9 +993,6 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
update_sm_hints (window); /* must come after transient_for */
|
||||
|
||||
if (client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
meta_window_x11_update_net_wm_type (window);
|
||||
|
||||
if (!window->override_redirect)
|
||||
meta_window_update_icon_now (window);
|
||||
|
||||
@@ -3042,39 +3038,42 @@ meta_window_save_rect (MetaWindow *window)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* save_user_window_placement:
|
||||
/**
|
||||
* force_save_user_window_placement:
|
||||
* @window: Store current position of this window for future reference
|
||||
* @rect: the rectangle with the position we want (in case it's not yet
|
||||
* assumed by the window, which happens for wayland resizes), or
|
||||
* %NULL to use the current window position
|
||||
* @force: save the user_rect regardless of whether the window is maximized or
|
||||
* fullscreen
|
||||
*
|
||||
* Save the user_rect regardless of whether the window is maximized or
|
||||
* fullscreen. See save_user_window_placement() for most uses.
|
||||
*/
|
||||
static void
|
||||
save_user_window_placement (MetaWindow *window,
|
||||
MetaRectangle *rect,
|
||||
gboolean force)
|
||||
force_save_user_window_placement (MetaWindow *window)
|
||||
{
|
||||
gboolean should_save = !META_WINDOW_MAXIMIZED (window) &&
|
||||
!META_WINDOW_TILED_SIDE_BY_SIDE (window) &&
|
||||
!window->fullscreen;
|
||||
meta_window_get_client_root_coords (window, &window->user_rect);
|
||||
}
|
||||
|
||||
if (force || should_save)
|
||||
/**
|
||||
* save_user_window_placement:
|
||||
* @window: Store current position of this window for future reference
|
||||
*
|
||||
* Save the user_rect, but only if the window is neither maximized nor
|
||||
* fullscreen, otherwise the window may snap back to those dimensions
|
||||
* (bug #461927).
|
||||
*/
|
||||
static void
|
||||
save_user_window_placement (MetaWindow *window)
|
||||
{
|
||||
if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED_SIDE_BY_SIDE (window) || window->fullscreen))
|
||||
{
|
||||
MetaRectangle user_rect;
|
||||
|
||||
if (rect)
|
||||
user_rect = *rect;
|
||||
else
|
||||
meta_window_get_client_root_coords (window, &user_rect);
|
||||
meta_window_get_client_root_coords (window, &user_rect);
|
||||
|
||||
if (force || !window->maximized_horizontally)
|
||||
if (!window->maximized_horizontally)
|
||||
{
|
||||
window->user_rect.x = user_rect.x;
|
||||
window->user_rect.width = user_rect.width;
|
||||
}
|
||||
if (force || !window->maximized_vertically)
|
||||
if (!window->maximized_vertically)
|
||||
{
|
||||
window->user_rect.y = user_rect.y;
|
||||
window->user_rect.height = user_rect.height;
|
||||
@@ -3584,7 +3583,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
|
||||
/* Make sure user_rect is current.
|
||||
*/
|
||||
save_user_window_placement (window, NULL, TRUE);
|
||||
force_save_user_window_placement (window);
|
||||
|
||||
/* When we unmaximize, if we're doing a mouse move also we could
|
||||
* get the window suddenly jumping to the upper left corner of
|
||||
@@ -3761,7 +3760,7 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
|
||||
/* Make sure user_rect is current.
|
||||
*/
|
||||
save_user_window_placement (window, NULL, TRUE);
|
||||
force_save_user_window_placement (window);
|
||||
|
||||
meta_window_update_layer (window);
|
||||
|
||||
@@ -4591,29 +4590,73 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
* it can be for maximized or fullscreen.
|
||||
*
|
||||
*/
|
||||
root_x_nw = new_rect.x;
|
||||
root_y_nw = new_rect.y;
|
||||
|
||||
/* First, save where we would like the client to be. This is used by the next
|
||||
* attach to determine if the client is really moving/resizing or not.
|
||||
*/
|
||||
window->expected_rect = new_rect;
|
||||
|
||||
if (is_wayland_resize)
|
||||
{
|
||||
/* This is a call to wl_surface_commit(), ignore the new_rect and
|
||||
* update the real client size to match the buffer size.
|
||||
*/
|
||||
|
||||
window->rect.width = w;
|
||||
window->rect.height = h;
|
||||
}
|
||||
|
||||
if (new_rect.width != window->rect.width ||
|
||||
new_rect.height != window->rect.height)
|
||||
{
|
||||
if (!is_wayland_resize)
|
||||
/* Politely ask for a new size, and wait until the next commit. */
|
||||
meta_wayland_surface_configure_notify (window->surface,
|
||||
new_rect.width,
|
||||
new_rect.height);
|
||||
/* We need to resize the client. Resizing is in two parts:
|
||||
* some of the movement happens immediately, and some happens as part
|
||||
* of the resizing (through dx/dy in wl_surface_attach).
|
||||
*
|
||||
* To do so, we need to compute the resize from the point of the view
|
||||
* of the client, and then adjust the immediate resize to match.
|
||||
*
|
||||
* dx/dy are the values we expect from the new attach(), while deltax/
|
||||
* deltay reflect the overall movement.
|
||||
*/
|
||||
MetaRectangle client_rect;
|
||||
int dx, dy;
|
||||
int deltax, deltay;
|
||||
|
||||
meta_rectangle_resize_with_gravity (&old_rect,
|
||||
&client_rect,
|
||||
gravity,
|
||||
new_rect.width,
|
||||
new_rect.height);
|
||||
|
||||
deltax = new_rect.x - old_rect.x;
|
||||
deltay = new_rect.y - old_rect.y;
|
||||
dx = client_rect.x - old_rect.x;
|
||||
dy = client_rect.y - old_rect.y;
|
||||
|
||||
if (deltax != dx || deltay != dy)
|
||||
need_move_client = TRUE;
|
||||
|
||||
window->rect.x += (deltax - dx);
|
||||
window->rect.y += (deltay - dy);
|
||||
|
||||
/* We need to update window->rect here, otherwise all sorts of
|
||||
bad stuff happens with interactive resizes... */
|
||||
need_resize_client = TRUE;
|
||||
meta_wayland_surface_configure_notify (window->surface,
|
||||
new_rect.width,
|
||||
new_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No resize happening, we can just move the window and live with it. */
|
||||
if (window->rect.x != new_rect.x ||
|
||||
window->rect.y != new_rect.y)
|
||||
need_move_client = TRUE;
|
||||
|
||||
if (window->rect.x != new_rect.x ||
|
||||
window->rect.y != new_rect.y)
|
||||
need_move_client = TRUE;
|
||||
|
||||
window->rect.x = new_rect.x;
|
||||
window->rect.y = new_rect.y;
|
||||
window->rect.width = new_rect.width;
|
||||
window->rect.height = new_rect.height;
|
||||
window->rect.x = new_rect.x;
|
||||
window->rect.y = new_rect.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4925,9 +4968,9 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
}
|
||||
|
||||
if (!window->placed && window->force_save_user_rect && !window->fullscreen)
|
||||
save_user_window_placement (window, &new_rect, TRUE);
|
||||
force_save_user_window_placement (window);
|
||||
else if (is_user_action)
|
||||
save_user_window_placement (window, &new_rect, FALSE);
|
||||
save_user_window_placement (window);
|
||||
|
||||
if (need_move_client || need_move_frame)
|
||||
g_signal_emit (window, window_signals[POSITION_CHANGED], 0);
|
||||
@@ -5028,10 +5071,10 @@ meta_window_move_resize_wayland (MetaWindow *window,
|
||||
meta_window_get_position (window, &x, &y);
|
||||
x += dx; y += dy;
|
||||
|
||||
if (x != window->rect.x || y != window->rect.y)
|
||||
if (x != window->expected_rect.x || y != window->expected_rect.y)
|
||||
flags |= META_IS_MOVE_ACTION;
|
||||
if (width != window->rect.width ||
|
||||
height != window->rect.height)
|
||||
if (width != window->expected_rect.width ||
|
||||
height != window->expected_rect.height)
|
||||
flags |= META_IS_RESIZE_ACTION;
|
||||
|
||||
meta_window_move_resize_internal (window, flags, NorthWestGravity,
|
||||
@@ -5605,37 +5648,6 @@ meta_window_get_outer_rect (const MetaWindow *window,
|
||||
meta_window_get_frame_rect (window, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_client_area_rect:
|
||||
* @window: a #MetaWindow
|
||||
* @rect: (out): pointer to a cairo rectangle
|
||||
*
|
||||
* Gets the rectangle for the boundaries of the client area, relative
|
||||
* to the frame. If the window is shaded, the height of the rectangle
|
||||
* is 0.
|
||||
*/
|
||||
void
|
||||
meta_window_get_client_area_rect (const MetaWindow *window,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
if (window->frame)
|
||||
{
|
||||
rect->x = window->frame->child_x;
|
||||
rect->y = window->frame->child_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->x = 0;
|
||||
rect->y = 0;
|
||||
}
|
||||
|
||||
rect->width = window->rect.width;
|
||||
if (window->shaded)
|
||||
rect->height = 0;
|
||||
else
|
||||
rect->height = window->rect.height;
|
||||
}
|
||||
|
||||
const char*
|
||||
meta_window_get_startup_id (MetaWindow *window)
|
||||
{
|
||||
@@ -6298,7 +6310,7 @@ meta_window_move_resize_request (MetaWindow *window,
|
||||
*
|
||||
* See also bug 426519.
|
||||
*/
|
||||
save_user_window_placement (window, NULL, FALSE);
|
||||
save_user_window_placement (window);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -8475,6 +8487,98 @@ update_resize (MetaWindow *window,
|
||||
g_get_current_time (&window->display->grab_last_moveresize_time);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Window window;
|
||||
int count;
|
||||
guint32 last_time;
|
||||
} EventScannerData;
|
||||
|
||||
static Bool
|
||||
find_last_time_predicate (Display *display,
|
||||
XEvent *ev,
|
||||
XPointer arg)
|
||||
{
|
||||
EventScannerData *esd = (void*) arg;
|
||||
XIEvent *xev;
|
||||
|
||||
if (ev->type != GenericEvent)
|
||||
return False;
|
||||
|
||||
/* We are peeking into events not yet handled by GDK,
|
||||
* Allocate cookie events here so we can handle XI2.
|
||||
*
|
||||
* GDK will handle later these events, and eventually
|
||||
* free the cookie data itself.
|
||||
*/
|
||||
XGetEventData (display, &ev->xcookie);
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype != XI_Motion)
|
||||
return False;
|
||||
|
||||
if (esd->window != ((XIDeviceEvent *) xev)->event)
|
||||
return False;
|
||||
|
||||
esd->count += 1;
|
||||
esd->last_time = xev->time;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_use_this_motion_notify (MetaWindow *window,
|
||||
XIDeviceEvent *xev)
|
||||
{
|
||||
EventScannerData esd;
|
||||
XEvent useless;
|
||||
|
||||
/* This code is copied from Owen's GDK code. */
|
||||
|
||||
if (window->display->grab_motion_notify_time != 0)
|
||||
{
|
||||
/* == is really the right test, but I'm all for paranoia */
|
||||
if (window->display->grab_motion_notify_time <=
|
||||
xev->time)
|
||||
{
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Arrived at event with time %u (waiting for %u), using it\n",
|
||||
(unsigned int)xev->time,
|
||||
window->display->grab_motion_notify_time);
|
||||
window->display->grab_motion_notify_time = 0;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; /* haven't reached the saved timestamp yet */
|
||||
}
|
||||
|
||||
esd.window = xev->event;
|
||||
esd.count = 0;
|
||||
esd.last_time = 0;
|
||||
|
||||
/* "useless" isn't filled in because the predicate never returns True */
|
||||
XCheckIfEvent (window->display->xdisplay,
|
||||
&useless,
|
||||
find_last_time_predicate,
|
||||
(XPointer) &esd);
|
||||
|
||||
if (esd.count > 0)
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Will skip %d motion events and use the event with time %u\n",
|
||||
esd.count, (unsigned int) esd.last_time);
|
||||
|
||||
if (esd.last_time == 0)
|
||||
return TRUE;
|
||||
else
|
||||
{
|
||||
/* Save this timestamp, and ignore all motion notify
|
||||
* until we get to the one with this stamp.
|
||||
*/
|
||||
window->display->grab_motion_notify_time = esd.last_time;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_tile_mode (MetaWindow *window)
|
||||
{
|
||||
@@ -8545,6 +8649,96 @@ meta_window_update_sync_request_counter (MetaWindow *window,
|
||||
}
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
void
|
||||
meta_window_handle_mouse_grab_op_xevent (MetaWindow *window,
|
||||
XIDeviceEvent *xevent)
|
||||
{
|
||||
gboolean is_window_root = (xevent->root == window->screen->xroot);
|
||||
|
||||
switch (xevent->evtype)
|
||||
{
|
||||
case XI_ButtonRelease:
|
||||
if (xevent->detail == 1 ||
|
||||
xevent->detail == meta_prefs_get_mouse_button_resize ())
|
||||
{
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
/* If the user was snap moving then ignore the button
|
||||
* release because they may have let go of shift before
|
||||
* releasing the mouse button and they almost certainly do
|
||||
* not want a non-snapped movement to occur from the button
|
||||
* release.
|
||||
*/
|
||||
if (!window->display->grab_last_user_action_was_snap)
|
||||
{
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else if (is_window_root)
|
||||
update_move (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
update_resize (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y,
|
||||
TRUE);
|
||||
|
||||
/* If a tiled window has been dragged free with a
|
||||
* mouse resize without snapping back to the tiled
|
||||
* state, it will end up with an inconsistent tile
|
||||
* mode on mouse release; cleaning the mode earlier
|
||||
* would break the ability to snap back to the tiled
|
||||
* state, so we wait until mouse release.
|
||||
*/
|
||||
update_tile_mode (window);
|
||||
}
|
||||
meta_display_end_grab_op (window->display, xevent->time);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XI_Motion:
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
{
|
||||
if (check_use_this_motion_notify (window, xevent))
|
||||
update_move (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y);
|
||||
}
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
{
|
||||
if (check_use_this_motion_notify (window, xevent))
|
||||
update_resize (window,
|
||||
xevent->mods.effective & ShiftMask,
|
||||
xevent->root_x,
|
||||
xevent->root_y,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
@@ -10297,15 +10491,25 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
MetaWindow *window = focus_data->window;
|
||||
MetaDisplay *display = window->display;
|
||||
MetaScreen *screen = window->screen;
|
||||
int root_x, root_y;
|
||||
Window root, child;
|
||||
double root_x, root_y, x, y;
|
||||
guint32 timestamp;
|
||||
ClutterActor *child;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
|
||||
goto out;
|
||||
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&root_x, &root_y, NULL);
|
||||
meta_error_trap_push (display);
|
||||
XIQueryPointer (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root, &child,
|
||||
&root_x, &root_y, &x, &y,
|
||||
&buttons, &mods, &group);
|
||||
meta_error_trap_pop (display);
|
||||
free (buttons.mask);
|
||||
|
||||
if (root_x != focus_data->pointer_x ||
|
||||
root_y != focus_data->pointer_y)
|
||||
@@ -10315,15 +10519,17 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
child = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (clutter_stage_get_default ()),
|
||||
CLUTTER_PICK_REACTIVE, root_x, root_y);
|
||||
if (!META_IS_SURFACE_ACTOR (child))
|
||||
/* Explicitly check for the overlay window, as get_focus_window_at_point()
|
||||
* may return windows that extend underneath the chrome (like
|
||||
* override-redirect or DESKTOP windows)
|
||||
*/
|
||||
if (child == meta_get_overlay_window (screen))
|
||||
goto out;
|
||||
|
||||
window =
|
||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
NULL, root_x, root_y);
|
||||
None, root_x, root_y);
|
||||
|
||||
if (window == NULL)
|
||||
goto out;
|
||||
|
@@ -214,6 +214,21 @@ typedef enum
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_SW,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_NW,
|
||||
|
||||
/* Alt+Tab */
|
||||
META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
|
||||
META_GRAB_OP_KEYBOARD_TABBING_DOCK,
|
||||
|
||||
/* Alt+Esc */
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL,
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_DOCK,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_GROUP,
|
||||
|
||||
/* Alt+F6 */
|
||||
META_GRAB_OP_KEYBOARD_TABBING_GROUP,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING,
|
||||
|
||||
/* Frame button ops */
|
||||
META_GRAB_OP_CLICKING_MINIMIZE,
|
||||
META_GRAB_OP_CLICKING_MAXIMIZE,
|
||||
|
@@ -62,6 +62,7 @@
|
||||
* @META_PREF_EDGE_TILING: edge tiling
|
||||
* @META_PREF_FORCE_FULLSCREEN: force fullscreen
|
||||
* @META_PREF_WORKSPACES_ONLY_ON_PRIMARY: workspaces only on primary
|
||||
* @META_PREF_NO_TAB_POPUP: no tab popup
|
||||
* @META_PREF_DRAGGABLE_BORDER_WIDTH: draggable border width
|
||||
* @META_PREF_AUTO_MAXIMIZE: auto-maximize
|
||||
*/
|
||||
@@ -99,6 +100,7 @@ typedef enum
|
||||
META_PREF_EDGE_TILING,
|
||||
META_PREF_FORCE_FULLSCREEN,
|
||||
META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
META_PREF_DRAGGABLE_BORDER_WIDTH,
|
||||
META_PREF_AUTO_MAXIMIZE
|
||||
} MetaPreference;
|
||||
@@ -161,6 +163,9 @@ void meta_prefs_set_force_fullscreen (gboolean whether);
|
||||
|
||||
gboolean meta_prefs_get_workspaces_only_on_primary (void);
|
||||
|
||||
gboolean meta_prefs_get_no_tab_popup (void);
|
||||
void meta_prefs_set_no_tab_popup (gboolean whether);
|
||||
|
||||
int meta_prefs_get_draggable_border_width (void);
|
||||
|
||||
gboolean meta_prefs_get_ignore_request_hide_titlebar (void);
|
||||
@@ -199,6 +204,8 @@ void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
|
||||
* @META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: FILLME
|
||||
* @META_KEYBINDING_ACTION_CYCLE_PANELS: FILLME
|
||||
* @META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: FILLME
|
||||
* @META_KEYBINDING_ACTION_TAB_POPUP_SELECT: FILLME
|
||||
* @META_KEYBINDING_ACTION_TAB_POPUP_CANCEL: FILLME
|
||||
* @META_KEYBINDING_ACTION_SHOW_DESKTOP: FILLME
|
||||
* @META_KEYBINDING_ACTION_PANEL_MAIN_MENU: FILLME
|
||||
* @META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: FILLME
|
||||
@@ -294,6 +301,8 @@ typedef enum _MetaKeyBindingAction
|
||||
META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD,
|
||||
META_KEYBINDING_ACTION_CYCLE_PANELS,
|
||||
META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
|
||||
META_KEYBINDING_ACTION_TAB_POPUP_SELECT,
|
||||
META_KEYBINDING_ACTION_TAB_POPUP_CANCEL,
|
||||
META_KEYBINDING_ACTION_SHOW_DESKTOP,
|
||||
META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
|
||||
META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
|
||||
@@ -371,6 +380,20 @@ typedef enum
|
||||
META_KEY_BINDING_IS_REVERSED = 1 << 3
|
||||
} MetaKeyBindingFlags;
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyHandlerFunc:
|
||||
* @display: a #MetaDisplay
|
||||
@@ -388,14 +411,45 @@ typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *bindings;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
GType meta_key_binding_get_type (void);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
|
||||
MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name);
|
||||
|
||||
void meta_prefs_get_window_binding (const char *name,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers);
|
||||
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
gboolean meta_prefs_get_visual_bell (void);
|
||||
gboolean meta_prefs_bell_is_audible (void);
|
||||
GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);
|
||||
|
@@ -2,31 +2,31 @@
|
||||
<schema id="org.gnome.mutter.wayland.keybindings" path="/org/gnome/mutter/wayland/keybindings/"
|
||||
gettext-domain="@GETTEXT_DOMAIN@">
|
||||
<key name="switch-to-session-1" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F1']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F1', 'XF86Switch_VT_1']]]></default>
|
||||
<_summary>Switch to VT 1</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-2" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F2']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F2', 'XF86Switch_VT_2']]]></default>
|
||||
<_summary>Switch to VT 2</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-3" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F3']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F3', 'XF86Switch_VT_3']]]></default>
|
||||
<_summary>Switch to VT 3</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-4" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F4']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F4', 'XF86Switch_VT_4']]]></default>
|
||||
<_summary>Switch to VT 4</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-5" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F5']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F5', 'XF86Switch_VT_5']]]></default>
|
||||
<_summary>Switch to VT 5</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-6" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F6']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F6', 'XF86Switch_VT_6']]]></default>
|
||||
<_summary>Switch to VT 6</_summary>
|
||||
</key>
|
||||
<key name="switch-to-session-7" type="as">
|
||||
<default><![CDATA[['<Primary><Alt>F7']]]></default>
|
||||
<default><![CDATA[['<Primary><Alt>F7', 'XF86Switch_VT_7']]]></default>
|
||||
<_summary>Switch to VT 7</_summary>
|
||||
</key>
|
||||
</schema>
|
||||
|
224
src/ui/draw-workspace.c
Normal file
224
src/ui/draw-workspace.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Draw a workspace */
|
||||
|
||||
/* This file should not be modified to depend on other files in
|
||||
* libwnck or mutter, since it's used in both of them
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "draw-workspace.h"
|
||||
#include "theme-private.h"
|
||||
|
||||
|
||||
static void
|
||||
get_window_rect (const WnckWindowDisplayInfo *win,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
const GdkRectangle *workspace_rect,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
double width_ratio, height_ratio;
|
||||
int x, y, width, height;
|
||||
|
||||
width_ratio = (double) workspace_rect->width / (double) screen_width;
|
||||
height_ratio = (double) workspace_rect->height / (double) screen_height;
|
||||
|
||||
x = win->x;
|
||||
y = win->y;
|
||||
width = win->width;
|
||||
height = win->height;
|
||||
|
||||
x *= width_ratio;
|
||||
y *= height_ratio;
|
||||
width *= width_ratio;
|
||||
height *= height_ratio;
|
||||
|
||||
x += workspace_rect->x;
|
||||
y += workspace_rect->y;
|
||||
|
||||
if (width < 3)
|
||||
width = 3;
|
||||
if (height < 3)
|
||||
height = 3;
|
||||
|
||||
rect->x = x;
|
||||
rect->y = y;
|
||||
rect->width = width;
|
||||
rect->height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_window (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
const WnckWindowDisplayInfo *win,
|
||||
const GdkRectangle *winrect,
|
||||
GtkStateFlags state)
|
||||
{
|
||||
GdkPixbuf *icon;
|
||||
int icon_x, icon_y, icon_w, icon_h;
|
||||
gboolean is_active;
|
||||
GdkRGBA color;
|
||||
GtkStyleContext *style;
|
||||
|
||||
is_active = win->is_active;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height);
|
||||
cairo_clip (cr);
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
if (is_active)
|
||||
meta_gtk_style_get_light_color (style, state, &color);
|
||||
else
|
||||
gtk_style_context_get_background_color (style, state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
winrect->x + 1, winrect->y + 1,
|
||||
MAX (0, winrect->width - 2), MAX (0, winrect->height - 2));
|
||||
cairo_fill (cr);
|
||||
|
||||
|
||||
icon = win->icon;
|
||||
|
||||
icon_w = icon_h = 0;
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
/* If the icon is too big, fall back to mini icon.
|
||||
* We don't arbitrarily scale the icon, because it's
|
||||
* just too slow on my Athlon 850.
|
||||
*/
|
||||
if (icon_w > (winrect->width - 2) ||
|
||||
icon_h > (winrect->height - 2))
|
||||
{
|
||||
icon = win->mini_icon;
|
||||
if (icon)
|
||||
{
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
/* Give up. */
|
||||
if (icon_w > (winrect->width - 2) ||
|
||||
icon_h > (winrect->height - 2))
|
||||
icon = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon_x = winrect->x + (winrect->width - icon_w) / 2;
|
||||
icon_y = winrect->y + (winrect->height - icon_h) / 2;
|
||||
|
||||
cairo_save (cr);
|
||||
gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y);
|
||||
cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h);
|
||||
cairo_clip (cr);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
gtk_style_context_get_color (style, state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_rectangle (cr,
|
||||
winrect->x + 0.5, winrect->y + 0.5,
|
||||
MAX (0, winrect->width - 1), MAX (0, winrect->height - 1));
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
void
|
||||
wnck_draw_workspace (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
GdkPixbuf *workspace_background,
|
||||
gboolean is_active,
|
||||
const WnckWindowDisplayInfo *windows,
|
||||
int n_windows)
|
||||
{
|
||||
int i;
|
||||
GdkRectangle workspace_rect;
|
||||
GtkStateFlags state;
|
||||
GtkStyleContext *style;
|
||||
|
||||
workspace_rect.x = x;
|
||||
workspace_rect.y = y;
|
||||
workspace_rect.width = width;
|
||||
workspace_rect.height = height;
|
||||
|
||||
if (is_active)
|
||||
state = GTK_STATE_FLAG_SELECTED;
|
||||
else if (workspace_background)
|
||||
state = GTK_STATE_FLAG_PRELIGHT;
|
||||
else
|
||||
state = GTK_STATE_FLAG_NORMAL;
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
if (workspace_background)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
meta_gtk_style_get_dark_color (style,state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_rectangle (cr, x, y, width, height);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
const WnckWindowDisplayInfo *win = &windows[i];
|
||||
GdkRectangle winrect;
|
||||
|
||||
get_window_rect (win, screen_width,
|
||||
screen_height, &workspace_rect, &winrect);
|
||||
|
||||
draw_window (widget,
|
||||
cr,
|
||||
win,
|
||||
&winrect,
|
||||
state);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
}
|
59
src/ui/draw-workspace.h
Normal file
59
src/ui/draw-workspace.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Draw a workspace */
|
||||
|
||||
/* This file should not be modified to depend on other files in
|
||||
* libwnck or metacity, since it's used in both of them
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WNCK_DRAW_WORKSPACE_H
|
||||
#define WNCK_DRAW_WORKSPACE_H
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
guint is_active : 1;
|
||||
|
||||
} WnckWindowDisplayInfo;
|
||||
|
||||
void wnck_draw_workspace (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
GdkPixbuf *workspace_background,
|
||||
gboolean is_active,
|
||||
const WnckWindowDisplayInfo *windows,
|
||||
int n_windows);
|
||||
|
||||
#endif
|
@@ -44,6 +44,8 @@
|
||||
static void meta_frames_destroy (GtkWidget *object);
|
||||
static void meta_frames_finalize (GObject *object);
|
||||
static void meta_frames_style_updated (GtkWidget *widget);
|
||||
static void meta_frames_map (GtkWidget *widget);
|
||||
static void meta_frames_unmap (GtkWidget *widget);
|
||||
|
||||
static void meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
@@ -132,6 +134,9 @@ meta_frames_class_init (MetaFramesClass *class)
|
||||
|
||||
widget_class->style_updated = meta_frames_style_updated;
|
||||
|
||||
widget_class->map = meta_frames_map;
|
||||
widget_class->unmap = meta_frames_unmap;
|
||||
|
||||
widget_class->draw = meta_frames_draw;
|
||||
widget_class->destroy_event = meta_frames_destroy_event;
|
||||
widget_class->button_press_event = meta_frames_button_press_event;
|
||||
@@ -226,7 +231,6 @@ meta_frames_init (MetaFrames *frames)
|
||||
|
||||
frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
|
||||
update_style_contexts (frames);
|
||||
|
||||
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
|
||||
@@ -518,26 +522,13 @@ MetaFrames*
|
||||
meta_frames_new (int screen_number)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
MetaFrames *frames;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
|
||||
frames = g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
"type", GTK_WINDOW_POPUP,
|
||||
NULL);
|
||||
|
||||
/* Put the window at an arbitrary offscreen location; the one place
|
||||
* it can't be is at -100x-100, since the meta_window_new() will
|
||||
* mistake it for a window created via meta_create_offscreen_window()
|
||||
* and ignore it, and we need this window to get frame-synchronization
|
||||
* messages so that GTK+'s style change handling works.
|
||||
*/
|
||||
gtk_window_move (GTK_WINDOW (frames), -200, -200);
|
||||
gtk_window_resize (GTK_WINDOW (frames), 1, 1);
|
||||
|
||||
return frames;
|
||||
return g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* In order to use a style with a window it has to be attached to that
|
||||
@@ -644,6 +635,22 @@ meta_frames_unmanage_window (MetaFrames *frames,
|
||||
meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_map (GtkWidget *widget)
|
||||
{
|
||||
/* We override the parent map function to a no-op because we don't
|
||||
* want to actually show the GDK window. But GTK needs to think that
|
||||
* the widget is mapped or it won't deliver the events we care about.
|
||||
*/
|
||||
gtk_widget_set_mapped (widget, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_unmap (GtkWidget *widget)
|
||||
{
|
||||
gtk_widget_set_mapped (widget, FALSE);
|
||||
}
|
||||
|
||||
static MetaUIFrame*
|
||||
meta_frames_lookup_window (MetaFrames *frames,
|
||||
Window xwindow)
|
||||
|
963
src/ui/tabpopup.c
Normal file
963
src/ui/tabpopup.c
Normal file
@@ -0,0 +1,963 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter popup window thing showing windows you can tab to */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2002 Red Hat, Inc.
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/util.h>
|
||||
#include "core.h"
|
||||
#include "tabpopup.h"
|
||||
/* FIXME these two includes are 100% broken ...
|
||||
*/
|
||||
#include "workspace-private.h"
|
||||
#include "frame.h"
|
||||
#include "draw-workspace.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <math.h>
|
||||
|
||||
#define OUTSIDE_SELECT_RECT 2
|
||||
#define INSIDE_SELECT_RECT 2
|
||||
|
||||
typedef struct _TabEntry TabEntry;
|
||||
|
||||
struct _TabEntry
|
||||
{
|
||||
MetaTabEntryKey key;
|
||||
char *title;
|
||||
GdkPixbuf *icon, *dimmed_icon;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle rect;
|
||||
GdkRectangle inner_rect;
|
||||
guint blank : 1;
|
||||
};
|
||||
|
||||
struct _MetaTabPopup
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *label;
|
||||
GList *current;
|
||||
GList *entries;
|
||||
TabEntry *current_selected_entry;
|
||||
GtkWidget *outline_window;
|
||||
gboolean outline;
|
||||
};
|
||||
|
||||
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
|
||||
static void select_image (GtkWidget *widget);
|
||||
static void unselect_image (GtkWidget *widget);
|
||||
|
||||
static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace);
|
||||
static void select_workspace (GtkWidget *widget);
|
||||
static void unselect_workspace (GtkWidget *widget);
|
||||
|
||||
static gboolean
|
||||
outline_window_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gpointer data)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
TabEntry *te;
|
||||
|
||||
popup = data;
|
||||
|
||||
if (!popup->outline || popup->current_selected_entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
te = popup->current_selected_entry;
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
0.5, 0.5,
|
||||
te->rect.width - 1,
|
||||
te->rect.height - 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
te->inner_rect.x - 0.5, te->inner_rect.y - 0.5,
|
||||
te->inner_rect.width + 1,
|
||||
te->inner_rect.height + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
dimm_icon (GdkPixbuf *pixbuf)
|
||||
{
|
||||
int x, y, pixel_stride, row_stride;
|
||||
guchar *row, *pixels;
|
||||
int w, h;
|
||||
GdkPixbuf *dimmed_pixbuf;
|
||||
|
||||
if (gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
dimmed_pixbuf = gdk_pixbuf_copy (pixbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
}
|
||||
|
||||
w = gdk_pixbuf_get_width (dimmed_pixbuf);
|
||||
h = gdk_pixbuf_get_height (dimmed_pixbuf);
|
||||
|
||||
pixel_stride = 4;
|
||||
|
||||
row = gdk_pixbuf_get_pixels (dimmed_pixbuf);
|
||||
row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf);
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
pixels = row;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixels[3] /= 2;
|
||||
pixels += pixel_stride;
|
||||
}
|
||||
row += row_stride;
|
||||
}
|
||||
return dimmed_pixbuf;
|
||||
}
|
||||
|
||||
static TabEntry*
|
||||
tab_entry_new (const MetaTabEntry *entry,
|
||||
gint screen_width,
|
||||
gboolean outline)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = g_new (TabEntry, 1);
|
||||
te->key = entry->key;
|
||||
te->title = NULL;
|
||||
if (entry->title)
|
||||
{
|
||||
gchar *str;
|
||||
gchar *tmp;
|
||||
gchar *formatter = "%s";
|
||||
|
||||
str = meta_g_utf8_strndup (entry->title, 4096);
|
||||
|
||||
if (entry->hidden)
|
||||
{
|
||||
formatter = "[%s]";
|
||||
}
|
||||
|
||||
tmp = g_markup_printf_escaped (formatter, str);
|
||||
g_free (str);
|
||||
str = tmp;
|
||||
|
||||
if (entry->demands_attention)
|
||||
{
|
||||
/* Escape the whole line of text then markup the text and
|
||||
* copy it back into the original buffer.
|
||||
*/
|
||||
tmp = g_strdup_printf ("<b>%s</b>", str);
|
||||
g_free (str);
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
te->title=g_strdup(str);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
te->widget = NULL;
|
||||
te->icon = entry->icon;
|
||||
te->blank = entry->blank;
|
||||
te->dimmed_icon = NULL;
|
||||
if (te->icon)
|
||||
{
|
||||
g_object_ref (G_OBJECT (te->icon));
|
||||
if (entry->hidden)
|
||||
te->dimmed_icon = dimm_icon (entry->icon);
|
||||
}
|
||||
|
||||
if (outline)
|
||||
{
|
||||
te->rect.x = entry->rect.x;
|
||||
te->rect.y = entry->rect.y;
|
||||
te->rect.width = entry->rect.width;
|
||||
te->rect.height = entry->rect.height;
|
||||
|
||||
te->inner_rect.x = entry->inner_rect.x;
|
||||
te->inner_rect.y = entry->inner_rect.y;
|
||||
te->inner_rect.width = entry->inner_rect.width;
|
||||
te->inner_rect.height = entry->inner_rect.height;
|
||||
}
|
||||
return te;
|
||||
}
|
||||
|
||||
MetaTabPopup*
|
||||
meta_ui_tab_popup_new (const MetaTabEntry *entries,
|
||||
int screen_number,
|
||||
int entry_count,
|
||||
int width,
|
||||
gboolean outline)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
int i, left, top;
|
||||
int height;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *align;
|
||||
GList *tmp;
|
||||
GtkWidget *frame;
|
||||
int max_label_width; /* the actual max width of the labels we create */
|
||||
AtkObject *obj;
|
||||
GdkScreen *screen;
|
||||
int screen_width;
|
||||
|
||||
popup = g_new (MetaTabPopup, 1);
|
||||
|
||||
popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
gtk_window_set_screen (GTK_WINDOW (popup->outline_window),
|
||||
screen);
|
||||
|
||||
gtk_widget_set_app_paintable (popup->outline_window, TRUE);
|
||||
gtk_widget_realize (popup->outline_window);
|
||||
|
||||
g_signal_connect (G_OBJECT (popup->outline_window), "draw",
|
||||
G_CALLBACK (outline_window_draw), popup);
|
||||
|
||||
popup->window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (popup->window),
|
||||
screen);
|
||||
|
||||
gtk_window_set_position (GTK_WINDOW (popup->window),
|
||||
GTK_WIN_POS_CENTER_ALWAYS);
|
||||
/* enable resizing, to get never-shrink behavior */
|
||||
gtk_window_set_resizable (GTK_WINDOW (popup->window),
|
||||
TRUE);
|
||||
popup->current = NULL;
|
||||
popup->entries = NULL;
|
||||
popup->current_selected_entry = NULL;
|
||||
popup->outline = outline;
|
||||
|
||||
screen_width = gdk_screen_get_width (screen);
|
||||
for (i = 0; i < entry_count; ++i)
|
||||
{
|
||||
TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline);
|
||||
popup->entries = g_list_prepend (popup->entries, new_entry);
|
||||
}
|
||||
|
||||
popup->entries = g_list_reverse (popup->entries);
|
||||
|
||||
g_assert (width > 0);
|
||||
height = i / width;
|
||||
if (i % width)
|
||||
height += 1;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (grid), 1);
|
||||
gtk_container_add (GTK_CONTAINER (popup->window),
|
||||
frame);
|
||||
gtk_container_add (GTK_CONTAINER (frame),
|
||||
vbox);
|
||||
|
||||
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (align),
|
||||
grid);
|
||||
|
||||
popup->label = gtk_label_new ("");
|
||||
|
||||
/* Set the accessible role of the label to a status bar so it
|
||||
* will emit name changed events that can be used by screen
|
||||
* readers.
|
||||
*/
|
||||
obj = gtk_widget_get_accessible (popup->label);
|
||||
atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
|
||||
|
||||
gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
|
||||
|
||||
max_label_width = 0;
|
||||
top = 0;
|
||||
tmp = popup->entries;
|
||||
|
||||
while (tmp && top < height)
|
||||
{
|
||||
left = 0;
|
||||
|
||||
while (tmp && left < width)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GtkRequisition req;
|
||||
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->blank)
|
||||
{
|
||||
/* just stick a widget here to avoid special cases */
|
||||
image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else if (outline)
|
||||
{
|
||||
if (te->dimmed_icon)
|
||||
{
|
||||
image = selectable_image_new (te->dimmed_icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = selectable_image_new (te->icon);
|
||||
}
|
||||
|
||||
gtk_misc_set_padding (GTK_MISC (image),
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1,
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1);
|
||||
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = selectable_workspace_new ((MetaWorkspace *) te->key);
|
||||
}
|
||||
|
||||
te->widget = image;
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
te->widget,
|
||||
left, top, 1, 1);
|
||||
|
||||
/* Efficiency rules! */
|
||||
gtk_label_set_markup (GTK_LABEL (popup->label),
|
||||
te->title);
|
||||
gtk_widget_get_preferred_size (popup->label, &req, NULL);
|
||||
max_label_width = MAX (max_label_width, req.width);
|
||||
|
||||
tmp = tmp->next;
|
||||
|
||||
++left;
|
||||
}
|
||||
|
||||
++top;
|
||||
}
|
||||
|
||||
/* remove all the temporary text */
|
||||
gtk_label_set_text (GTK_LABEL (popup->label), "");
|
||||
/* Make it so that we ellipsize if the text is too long */
|
||||
gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END);
|
||||
|
||||
/* Limit the window size to no bigger than screen_width/4 */
|
||||
if (max_label_width>(screen_width/4))
|
||||
{
|
||||
max_label_width = screen_width/4;
|
||||
}
|
||||
|
||||
max_label_width += 20; /* add random padding */
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (popup->window),
|
||||
max_label_width,
|
||||
-1);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
static void
|
||||
free_tab_entry (gpointer data, gpointer user_data)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = data;
|
||||
|
||||
g_free (te->title);
|
||||
if (te->icon)
|
||||
g_object_unref (G_OBJECT (te->icon));
|
||||
if (te->dimmed_icon)
|
||||
g_object_unref (G_OBJECT (te->dimmed_icon));
|
||||
|
||||
g_free (te);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_free (MetaTabPopup *popup)
|
||||
{
|
||||
meta_verbose ("Destroying tab popup window\n");
|
||||
|
||||
if (!popup)
|
||||
{
|
||||
meta_warning ("NULL passed to meta_ui_tab_popup_free\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_destroy (popup->outline_window);
|
||||
gtk_widget_destroy (popup->window);
|
||||
|
||||
g_list_foreach (popup->entries, free_tab_entry, NULL);
|
||||
|
||||
g_list_free (popup->entries);
|
||||
|
||||
g_free (popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing)
|
||||
{
|
||||
if (showing)
|
||||
{
|
||||
gtk_widget_show_all (popup->window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_widget_get_visible (popup->window))
|
||||
{
|
||||
meta_verbose ("Hiding tab popup window\n");
|
||||
gtk_widget_hide (popup->window);
|
||||
meta_core_increment_event_serial (
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_entry (MetaTabPopup *popup,
|
||||
TabEntry *te)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GdkWindow *window;
|
||||
|
||||
|
||||
if (popup->current_selected_entry)
|
||||
{
|
||||
if (popup->outline)
|
||||
unselect_image (popup->current_selected_entry->widget);
|
||||
else
|
||||
unselect_workspace (popup->current_selected_entry->widget);
|
||||
}
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (popup->label), te->title);
|
||||
|
||||
if (popup->outline)
|
||||
select_image (te->widget);
|
||||
else
|
||||
select_workspace (te->widget);
|
||||
|
||||
if (popup->outline)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
cairo_region_t *inner_region;
|
||||
GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
window = gtk_widget_get_window (popup->outline_window);
|
||||
|
||||
/* Do stuff behind gtk's back */
|
||||
gdk_window_hide (window);
|
||||
meta_core_increment_event_serial (
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
|
||||
rect = te->rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
|
||||
gdk_window_move_resize (window,
|
||||
te->rect.x, te->rect.y,
|
||||
te->rect.width, te->rect.height);
|
||||
|
||||
gdk_window_set_background_rgba (window, &black);
|
||||
|
||||
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
inner_region = cairo_region_create_rectangle (&te->inner_rect);
|
||||
cairo_region_subtract (region, inner_region);
|
||||
cairo_region_destroy (inner_region);
|
||||
|
||||
gdk_window_shape_combine_region (window,
|
||||
region,
|
||||
0, 0);
|
||||
|
||||
cairo_region_destroy (region);
|
||||
|
||||
|
||||
/* This should piss off gtk a bit, but we don't want to raise
|
||||
* above the tab popup. So, instead of calling gtk_widget_show,
|
||||
* we manually set the window as mapped and then manually map it
|
||||
* with gdk functions.
|
||||
*/
|
||||
gtk_widget_set_mapped (popup->outline_window, TRUE);
|
||||
gdk_window_show_unraised (window);
|
||||
}
|
||||
|
||||
/* Must be before we handle an expose for the outline window */
|
||||
popup->current_selected_entry = te;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_forward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->next;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = popup->entries;
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_backward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->prev;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = g_list_last (popup->entries);
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
MetaTabEntryKey
|
||||
meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
return te->key;
|
||||
}
|
||||
else
|
||||
return (MetaTabEntryKey)None;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
MetaTabEntryKey key)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
/* Note, "key" may not be in the list of entries; other code assumes
|
||||
* it's OK to pass in a key that isn't.
|
||||
*/
|
||||
|
||||
tmp = popup->entries;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->key == key)
|
||||
{
|
||||
popup->current = tmp;
|
||||
|
||||
display_entry (popup, te);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ())
|
||||
#define META_SELECT_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage))
|
||||
|
||||
typedef struct _MetaSelectImage MetaSelectImage;
|
||||
typedef struct _MetaSelectImageClass MetaSelectImageClass;
|
||||
|
||||
struct _MetaSelectImage
|
||||
{
|
||||
GtkImage parent_instance;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectImageClass
|
||||
{
|
||||
GtkImageClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_image_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GtkWidget*
|
||||
selectable_image_new (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
w = g_object_new (meta_select_image_get_type (), NULL);
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
select_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_image_class_init (MetaSelectImageClass *klass);
|
||||
static gboolean meta_select_image_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
|
||||
static GtkImageClass *parent_class;
|
||||
|
||||
GType
|
||||
meta_select_image_get_type (void)
|
||||
{
|
||||
static GType image_type = 0;
|
||||
|
||||
if (!image_type)
|
||||
{
|
||||
static const GTypeInfo image_info =
|
||||
{
|
||||
sizeof (MetaSelectImageClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_image_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectImage),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0);
|
||||
}
|
||||
|
||||
return image_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_image_class_init (MetaSelectImageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
parent_class = g_type_class_peek (gtk_image_get_type ());
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->draw = meta_select_image_draw;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_select_image_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (META_SELECT_IMAGE (widget)->selected)
|
||||
{
|
||||
GtkMisc *misc;
|
||||
GtkRequisition requisition;
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
int x, y, w, h;
|
||||
gint xpad, ypad;
|
||||
gfloat xalign, yalign;
|
||||
|
||||
misc = GTK_MISC (widget);
|
||||
|
||||
gtk_widget_get_requisition (widget, &requisition);
|
||||
gtk_misc_get_alignment (misc, &xalign, &yalign);
|
||||
gtk_misc_get_padding (misc, &xpad, &ypad);
|
||||
|
||||
x = (allocation.width - (requisition.width - xpad * 2)) * xalign + 0.5;
|
||||
y = (allocation.height - (requisition.height - ypad * 2)) * yalign + 0.5;
|
||||
|
||||
x -= INSIDE_SELECT_RECT + 1;
|
||||
y -= INSIDE_SELECT_RECT + 1;
|
||||
|
||||
w = requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
h = requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_set_state (context,
|
||||
gtk_widget_get_state_flags (widget));
|
||||
|
||||
gtk_style_context_lookup_color (context, "color", &color);
|
||||
|
||||
cairo_set_line_width (cr, 2.0);
|
||||
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
|
||||
|
||||
cairo_rectangle (cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
}
|
||||
|
||||
return GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ())
|
||||
#define META_SELECT_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace))
|
||||
|
||||
typedef struct _MetaSelectWorkspace MetaSelectWorkspace;
|
||||
typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass;
|
||||
|
||||
struct _MetaSelectWorkspace
|
||||
{
|
||||
GtkDrawingArea parent_instance;
|
||||
MetaWorkspace *workspace;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectWorkspaceClass
|
||||
{
|
||||
GtkDrawingAreaClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_workspace_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#define SELECT_OUTLINE_WIDTH 2
|
||||
#define MINI_WORKSPACE_WIDTH 48
|
||||
|
||||
static GtkWidget*
|
||||
selectable_workspace_new (MetaWorkspace *workspace)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
double screen_aspect;
|
||||
|
||||
widget = g_object_new (meta_select_workspace_get_type (), NULL);
|
||||
|
||||
screen_aspect = (double) workspace->screen->rect.height /
|
||||
(double) workspace->screen->rect.width;
|
||||
|
||||
/* account for select rect */
|
||||
gtk_widget_set_size_request (widget,
|
||||
MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2,
|
||||
MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2);
|
||||
|
||||
META_SELECT_WORKSPACE (widget)->workspace = workspace;
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void
|
||||
select_workspace (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_WORKSPACE(widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_workspace (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_WORKSPACE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass);
|
||||
|
||||
static gboolean meta_select_workspace_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
|
||||
GType
|
||||
meta_select_workspace_get_type (void)
|
||||
{
|
||||
static GType workspace_type = 0;
|
||||
|
||||
if (!workspace_type)
|
||||
{
|
||||
static const GTypeInfo workspace_info =
|
||||
{
|
||||
sizeof (MetaSelectWorkspaceClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_workspace_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectWorkspace),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
|
||||
"MetaSelectWorkspace",
|
||||
&workspace_info,
|
||||
0);
|
||||
}
|
||||
|
||||
return workspace_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->draw = meta_select_workspace_draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_convert_meta_to_wnck:
|
||||
* @window: the #MetaWindow
|
||||
* @screen: the #MetaScreen the window is on
|
||||
*
|
||||
* Converts a #MetaWindow to a #WnckWindowDisplayInfo window
|
||||
* that is used to build a thumbnail of a workspace.
|
||||
**/
|
||||
static WnckWindowDisplayInfo
|
||||
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
||||
{
|
||||
WnckWindowDisplayInfo wnck_window;
|
||||
wnck_window.icon = window->icon;
|
||||
wnck_window.mini_icon = window->mini_icon;
|
||||
wnck_window.is_active = window->has_focus;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
wnck_window.x = window->frame->rect.x;
|
||||
wnck_window.y = window->frame->rect.y;
|
||||
wnck_window.width = window->frame->rect.width;
|
||||
wnck_window.height = window->frame->rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
wnck_window.x = window->rect.x;
|
||||
wnck_window.y = window->rect.y;
|
||||
wnck_window.width = window->rect.width;
|
||||
wnck_window.height = window->rect.height;
|
||||
}
|
||||
return wnck_window;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
meta_select_workspace_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
WnckWindowDisplayInfo *windows;
|
||||
GtkAllocation allocation;
|
||||
int i, n_windows;
|
||||
GList *tmp, *list;
|
||||
|
||||
workspace = META_SELECT_WORKSPACE (widget)->workspace;
|
||||
|
||||
list = meta_stack_list_windows (workspace->screen->stack, workspace);
|
||||
n_windows = g_list_length (list);
|
||||
windows = g_new (WnckWindowDisplayInfo, n_windows);
|
||||
|
||||
tmp = list;
|
||||
i = 0;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *window;
|
||||
gboolean ignoreable_sticky;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
ignoreable_sticky = window->on_all_workspaces &&
|
||||
workspace != workspace->screen->active_workspace;
|
||||
|
||||
if (window->skip_pager ||
|
||||
!meta_window_showing_on_its_workspace (window) ||
|
||||
window->unmaps_pending ||
|
||||
ignoreable_sticky)
|
||||
{
|
||||
--n_windows;
|
||||
}
|
||||
else
|
||||
{
|
||||
windows[i] = meta_convert_meta_to_wnck (window, workspace->screen);
|
||||
i++;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
wnck_draw_workspace (widget,
|
||||
cr,
|
||||
SELECT_OUTLINE_WIDTH,
|
||||
SELECT_OUTLINE_WIDTH,
|
||||
allocation.width - SELECT_OUTLINE_WIDTH * 2,
|
||||
allocation.height - SELECT_OUTLINE_WIDTH * 2,
|
||||
workspace->screen->rect.width,
|
||||
workspace->screen->rect.height,
|
||||
NULL,
|
||||
(workspace->screen->active_workspace == workspace),
|
||||
windows,
|
||||
n_windows);
|
||||
|
||||
g_free (windows);
|
||||
|
||||
if (META_SELECT_WORKSPACE (widget)->selected)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_set_state (context,
|
||||
gtk_widget_get_state_flags (widget));
|
||||
|
||||
gtk_style_context_lookup_color (context, "color", &color);
|
||||
|
||||
cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH);
|
||||
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0,
|
||||
allocation.width - SELECT_OUTLINE_WIDTH,
|
||||
allocation.height - SELECT_OUTLINE_WIDTH);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
65
src/ui/tabpopup.h
Normal file
65
src/ui/tabpopup.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter tab popup window */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef META_TABPOPUP_H
|
||||
#define META_TABPOPUP_H
|
||||
|
||||
/* Don't include gtk.h or gdk.h here */
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct _MetaTabEntry MetaTabEntry;
|
||||
typedef struct _MetaTabPopup MetaTabPopup;
|
||||
typedef void *MetaTabEntryKey;
|
||||
|
||||
struct _MetaTabEntry
|
||||
{
|
||||
MetaTabEntryKey key;
|
||||
const char *title;
|
||||
GdkPixbuf *icon;
|
||||
MetaRectangle rect;
|
||||
MetaRectangle inner_rect;
|
||||
guint blank : 1;
|
||||
guint hidden : 1;
|
||||
guint demands_attention : 1;
|
||||
};
|
||||
|
||||
MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
|
||||
int screen_number,
|
||||
int entry_count,
|
||||
int width,
|
||||
gboolean outline);
|
||||
void meta_ui_tab_popup_free (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing);
|
||||
void meta_ui_tab_popup_forward (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_backward (MetaTabPopup *popup);
|
||||
MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
MetaTabEntryKey key);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -295,12 +295,9 @@ meta_ui_new (Display *xdisplay,
|
||||
g_assert (gdisplay == gdk_display_get_default ());
|
||||
|
||||
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
|
||||
/* GTK+ needs the frame-sync protocol to work in order to properly
|
||||
* handle style changes. This means that the dummy widget we create
|
||||
* to get the style for title bars actually needs to be mapped
|
||||
* and fully tracked as a MetaWindow. Horrible, but mostly harmless -
|
||||
* the window is a 1x1 overide redirect window positioned offscreen.
|
||||
*/
|
||||
/* This does not actually show any widget. MetaFrames has been hacked so
|
||||
* that showing it doesn't actually do anything. But we need the flags
|
||||
* set for GTK to deliver events properly. */
|
||||
gtk_widget_show (GTK_WIDGET (ui->frames));
|
||||
|
||||
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
|
||||
|
@@ -178,4 +178,6 @@ int meta_ui_get_drag_threshold (MetaUI *ui);
|
||||
|
||||
MetaUIDirection meta_ui_get_direction (void);
|
||||
|
||||
#include "tabpopup.h"
|
||||
|
||||
#endif
|
||||
|
@@ -222,6 +222,7 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
|
||||
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
keyboard->focus_surface = NULL;
|
||||
|
||||
if (keyboard->focus_resource)
|
||||
@@ -236,6 +237,7 @@ keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
|
||||
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
keyboard->focus_resource = NULL;
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,6 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct _MetaWaylandKeyboardGrabInterface
|
||||
{
|
||||
|
@@ -49,6 +49,7 @@
|
||||
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "xdg-shell-server-protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -59,6 +60,7 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
pointer->focus_surface = NULL;
|
||||
|
||||
if (pointer->focus_resource)
|
||||
@@ -73,6 +75,7 @@ pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
|
||||
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
|
||||
@@ -527,7 +530,14 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
||||
|
||||
wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link)
|
||||
{
|
||||
meta_wayland_surface_popup_done (popup->surface);
|
||||
MetaWaylandSurfaceExtension *xdg_popup = &popup->surface->xdg_popup;
|
||||
struct wl_client *client = wl_resource_get_client (xdg_popup->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial;
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
xdg_popup_send_popup_done (xdg_popup->resource, serial);
|
||||
wl_list_remove (&popup->surface_destroy_listener.link);
|
||||
wl_list_remove (&popup->link);
|
||||
g_slice_free (MetaWaylandPopup, popup);
|
||||
@@ -587,10 +597,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
popup->grab = grab;
|
||||
popup->surface = surface;
|
||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||
if (surface->xdg_popup.resource)
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
|
||||
wl_list_insert (&grab->all_popups, &popup->link);
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define META_WAYLAND_PRIVATE_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <glib.h>
|
||||
@@ -30,7 +31,7 @@
|
||||
#include "meta-weston-launch.h"
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-wayland-versions.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
@@ -90,8 +91,30 @@ struct _MetaWaylandCompositor
|
||||
MetaWaylandSeat *seat;
|
||||
};
|
||||
|
||||
void meta_wayland_init (void);
|
||||
void meta_wayland_finalize (void);
|
||||
|
||||
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
|
||||
* API after meta_wayland_init() has been called. */
|
||||
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
|
||||
|
||||
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
|
||||
|
||||
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
int vt,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_WAYLAND_PRIVATE_H */
|
||||
|
@@ -82,6 +82,7 @@ surface_handle_buffer_destroy (struct wl_listener *listener, void *data)
|
||||
wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"Destroyed buffer while it was attached to the surface");
|
||||
surface->buffer = NULL;
|
||||
wl_list_remove (&surface->buffer_destroy_listener.link);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -261,6 +262,9 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
|
||||
CoglError *catch_error = NULL;
|
||||
CoglTexture *texture;
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
|
||||
buffer->resource,
|
||||
&catch_error));
|
||||
@@ -291,7 +295,7 @@ actor_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaSurfaceActor *surface_actor = surface->surface_actor;
|
||||
MetaWaylandBuffer *buffer = pending->buffer;
|
||||
|
||||
if (buffer_changed && buffer)
|
||||
if (buffer_changed)
|
||||
{
|
||||
ensure_buffer_texture (buffer);
|
||||
meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
|
||||
@@ -646,9 +650,18 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
static void
|
||||
destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
|
||||
{
|
||||
wl_list_remove (&extension->surface_destroy_listener.link);
|
||||
extension->resource = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
extension_handle_surface_destroy (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *extension = wl_container_of (listener, extension, surface_destroy_listener);
|
||||
wl_resource_destroy (extension->resource);
|
||||
}
|
||||
|
||||
static int
|
||||
get_resource_version (struct wl_resource *master_resource,
|
||||
int max_version)
|
||||
@@ -658,22 +671,23 @@ get_resource_version (struct wl_resource *master_resource,
|
||||
|
||||
static gboolean
|
||||
create_surface_extension (MetaWaylandSurfaceExtension *extension,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *master_resource,
|
||||
struct wl_resource *surface_resource,
|
||||
guint32 id,
|
||||
int max_version,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation,
|
||||
wl_resource_destroy_func_t destructor,
|
||||
MetaWaylandSurface *surface,
|
||||
struct wl_resource *master_resource,
|
||||
guint32 id)
|
||||
wl_resource_destroy_func_t destructor)
|
||||
{
|
||||
struct wl_client *client;
|
||||
|
||||
if (extension->resource != NULL)
|
||||
return FALSE;
|
||||
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
extension->resource = wl_resource_create (client, interface, get_resource_version (master_resource, max_version), id);
|
||||
wl_resource_set_implementation (extension->resource, implementation, surface, destructor);
|
||||
wl_resource_set_implementation (extension->resource, implementation, extension, destructor);
|
||||
|
||||
extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
|
||||
wl_resource_add_destroy_listener (surface_resource, &extension->surface_destroy_listener);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -700,10 +714,11 @@ xdg_shell_pong (struct wl_client *client,
|
||||
static void
|
||||
xdg_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_surface);
|
||||
destroy_surface_extension (xdg_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -718,7 +733,8 @@ xdg_surface_set_transient_for (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *parent_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
MetaWindow *transient_for = NULL;
|
||||
|
||||
if (parent_resource)
|
||||
@@ -738,7 +754,8 @@ xdg_surface_set_margin (struct wl_client *client,
|
||||
int32_t top_margin,
|
||||
int32_t bottom_margin)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.frame_extents_changed = TRUE;
|
||||
surface->pending.frame_extents.left = left_margin;
|
||||
@@ -752,7 +769,8 @@ xdg_surface_set_title (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
}
|
||||
@@ -762,7 +780,8 @@ xdg_surface_set_app_id (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *app_id)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
meta_window_set_wm_class (surface->window, app_id, app_id);
|
||||
}
|
||||
@@ -797,7 +816,8 @@ xdg_surface_move (struct wl_client *client,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
@@ -808,7 +828,7 @@ xdg_surface_move (struct wl_client *client,
|
||||
}
|
||||
|
||||
static MetaGrabOp
|
||||
grab_op_for_xdg_surface_resize_edge (int edge)
|
||||
grab_op_for_edge (int edge)
|
||||
{
|
||||
switch (edge)
|
||||
{
|
||||
@@ -842,14 +862,15 @@ xdg_surface_resize (struct wl_client *client,
|
||||
guint32 edges)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_xdg_surface_resize_edge (edges));
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -864,7 +885,8 @@ static void
|
||||
xdg_surface_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.fullscreen.changed = TRUE;
|
||||
surface->pending.fullscreen.value = TRUE;
|
||||
@@ -885,7 +907,8 @@ static void
|
||||
xdg_surface_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.maximized.changed = TRUE;
|
||||
surface->pending.maximized.value = TRUE;
|
||||
@@ -895,7 +918,8 @@ static void
|
||||
xdg_surface_unset_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.maximized.changed = TRUE;
|
||||
surface->pending.maximized.value = FALSE;
|
||||
@@ -905,7 +929,8 @@ static void
|
||||
xdg_surface_set_minimized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
meta_window_minimize (surface->window);
|
||||
}
|
||||
@@ -934,12 +959,11 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_surface,
|
||||
if (!create_surface_extension (&surface->xdg_surface, client, surface_resource, resource, id,
|
||||
META_XDG_SURFACE_VERSION,
|
||||
&xdg_surface_interface,
|
||||
&meta_wayland_xdg_surface_interface,
|
||||
xdg_surface_destructor,
|
||||
surface, resource, id))
|
||||
xdg_surface_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -954,10 +978,11 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
static void
|
||||
xdg_popup_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_popup);
|
||||
destroy_surface_extension (xdg_popup);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -990,12 +1015,11 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||
return;
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_popup,
|
||||
if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id,
|
||||
META_XDG_POPUP_VERSION,
|
||||
&xdg_popup_interface,
|
||||
&meta_wayland_xdg_popup_interface,
|
||||
xdg_popup_destructor,
|
||||
surface, resource, id))
|
||||
xdg_popup_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1078,264 +1102,13 @@ bind_xdg_shell (struct wl_client *client,
|
||||
wl_client_add_destroy_listener (client, &xdg_shell->client_destroy_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (&surface->wl_shell_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_pong (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
meta_display_pong_for_serial (display, serial);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_move (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING);
|
||||
}
|
||||
|
||||
static MetaGrabOp
|
||||
grab_op_for_wl_shell_surface_resize_edge (int edge)
|
||||
{
|
||||
switch (edge)
|
||||
{
|
||||
case WL_SHELL_SURFACE_RESIZE_TOP_LEFT:
|
||||
return META_GRAB_OP_RESIZING_NW;
|
||||
case WL_SHELL_SURFACE_RESIZE_TOP:
|
||||
return META_GRAB_OP_RESIZING_N;
|
||||
case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT:
|
||||
return META_GRAB_OP_RESIZING_NE;
|
||||
case WL_SHELL_SURFACE_RESIZE_RIGHT:
|
||||
return META_GRAB_OP_RESIZING_E;
|
||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT:
|
||||
return META_GRAB_OP_RESIZING_SE;
|
||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM:
|
||||
return META_GRAB_OP_RESIZING_S;
|
||||
case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT:
|
||||
return META_GRAB_OP_RESIZING_SW;
|
||||
case WL_SHELL_SURFACE_RESIZE_LEFT:
|
||||
return META_GRAB_OP_RESIZING_W;
|
||||
default:
|
||||
g_warning ("invalid edge: %d", edge);
|
||||
return META_GRAB_OP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_resize (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial,
|
||||
uint32_t edges)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
begin_grab_op_on_surface (surface, seat, grab_op_for_wl_shell_surface_resize_edge (edges));
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
SURFACE_STATE_TOPLEVEL,
|
||||
SURFACE_STATE_FULLSCREEN,
|
||||
SURFACE_STATE_MAXIMIZED,
|
||||
} SurfaceState;
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_state (MetaWaylandSurface *surface,
|
||||
SurfaceState state)
|
||||
{
|
||||
if (state == SURFACE_STATE_FULLSCREEN)
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
else
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
|
||||
if (state == SURFACE_STATE_MAXIMIZED)
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
|
||||
else
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_toplevel (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_transient (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *parent_resource,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
uint32_t flags)
|
||||
{
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
|
||||
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
meta_window_move (surface->window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
surface->window->placed = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t method,
|
||||
uint32_t framerate,
|
||||
struct wl_resource *output)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_FULLSCREEN);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_popup (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial,
|
||||
struct wl_resource *parent_resource,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
uint32_t flags)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
|
||||
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
meta_window_move (surface->window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
surface->window->placed = TRUE;
|
||||
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *output)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
wl_shell_surface_set_state (surface, SURFACE_STATE_MAXIMIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_title (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_shell_surface_set_class (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *class_)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_window_set_wm_class (surface->window, class_, class_);
|
||||
}
|
||||
|
||||
static const struct wl_shell_surface_interface meta_wayland_wl_shell_surface_interface = {
|
||||
wl_shell_surface_pong,
|
||||
wl_shell_surface_move,
|
||||
wl_shell_surface_resize,
|
||||
wl_shell_surface_set_toplevel,
|
||||
wl_shell_surface_set_transient,
|
||||
wl_shell_surface_set_fullscreen,
|
||||
wl_shell_surface_set_popup,
|
||||
wl_shell_surface_set_maximized,
|
||||
wl_shell_surface_set_title,
|
||||
wl_shell_surface_set_class,
|
||||
};
|
||||
|
||||
static void
|
||||
wl_shell_get_shell_surface (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t id,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->wl_shell_surface,
|
||||
META_WL_SHELL_SURFACE_VERSION,
|
||||
&wl_shell_surface_interface,
|
||||
&meta_wayland_wl_shell_surface_interface,
|
||||
wl_shell_surface_destructor,
|
||||
surface, resource, id))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"wl_shell::get_shell_surface already requested");
|
||||
return;
|
||||
}
|
||||
|
||||
meta_wayland_surface_make_toplevel (surface);
|
||||
surface->window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
}
|
||||
|
||||
static const struct wl_shell_interface meta_wayland_wl_shell_interface = {
|
||||
wl_shell_get_shell_surface,
|
||||
};
|
||||
|
||||
static void
|
||||
bind_wl_shell (struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &wl_shell_interface,
|
||||
MIN (META_WL_SHELL_VERSION, version), id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_wl_shell_interface, data, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
|
||||
|
||||
destroy_surface_extension (&surface->gtk_surface);
|
||||
destroy_surface_extension (gtk_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1348,7 +1121,8 @@ set_dbus_properties (struct wl_client *client,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
|
||||
|
||||
/* Broken client, let it die instead of us */
|
||||
if (!surface->window)
|
||||
@@ -1378,12 +1152,11 @@ get_gtk_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->gtk_surface,
|
||||
if (!create_surface_extension (&surface->gtk_surface, client, surface_resource, resource, id,
|
||||
META_GTK_SURFACE_VERSION,
|
||||
>k_surface_interface,
|
||||
&meta_wayland_gtk_surface_interface,
|
||||
gtk_surface_destructor,
|
||||
surface, resource, id))
|
||||
gtk_surface_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1480,7 +1253,8 @@ unparent_actor (MetaWaylandSurface *surface)
|
||||
static void
|
||||
wl_subsurface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
if (surface->sub.parent)
|
||||
{
|
||||
@@ -1492,7 +1266,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
double_buffered_state_destroy (&surface->sub.pending_surface_state);
|
||||
destroy_surface_extension (&surface->subsurface);
|
||||
destroy_surface_extension (subsurface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1508,7 +1282,8 @@ wl_subsurface_set_position (struct wl_client *client,
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
surface->sub.pending_x = x;
|
||||
surface->sub.pending_y = y;
|
||||
@@ -1558,7 +1333,8 @@ wl_subsurface_place_above (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *sibling_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
|
||||
|
||||
if (!is_valid_sibling (surface, sibling))
|
||||
@@ -1580,7 +1356,8 @@ wl_subsurface_place_below (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *sibling_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
|
||||
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
|
||||
|
||||
if (!is_valid_sibling (surface, sibling))
|
||||
@@ -1601,7 +1378,10 @@ static void
|
||||
wl_subsurface_set_sync (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface =
|
||||
wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
surface->sub.synchronous = TRUE;
|
||||
}
|
||||
@@ -1610,7 +1390,10 @@ static void
|
||||
wl_subsurface_set_desync (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurfaceExtension *subsurface =
|
||||
wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface =
|
||||
wl_container_of (subsurface, surface, subsurface);
|
||||
|
||||
if (surface->sub.synchronous)
|
||||
subsurface_parent_surface_committed (surface);
|
||||
@@ -1656,12 +1439,11 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->subsurface,
|
||||
if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id,
|
||||
META_GTK_SURFACE_VERSION,
|
||||
&wl_subsurface_interface,
|
||||
&meta_wayland_subsurface_interface,
|
||||
wl_subsurface_destructor,
|
||||
surface, resource, id))
|
||||
wl_subsurface_destructor))
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1707,11 +1489,6 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor)
|
||||
compositor, bind_xdg_shell) == NULL)
|
||||
g_error ("Failed to register a global xdg-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
&wl_shell_interface, 1,
|
||||
compositor, bind_wl_shell) == NULL)
|
||||
g_error ("Failed to register a global wl-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
>k_shell_interface,
|
||||
META_GTK_SHELL_VERSION,
|
||||
@@ -1733,9 +1510,6 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
if (surface->xdg_surface.resource)
|
||||
xdg_surface_send_configure (surface->xdg_surface.resource,
|
||||
new_width, new_height);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
|
||||
0, new_width, new_height);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1756,23 +1530,16 @@ void
|
||||
meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
guint32 serial)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_resource *xdg_shell = get_xdg_shell_for_client (client);
|
||||
|
||||
if (xdg_shell == NULL)
|
||||
{
|
||||
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
|
||||
return;
|
||||
}
|
||||
|
||||
xdg_shell_send_ping (xdg_shell, serial);
|
||||
}
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
if (xdg_shell == NULL)
|
||||
{
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
|
||||
g_warning ("Trying to ping a surface without an xdg_shell bound. How does this happen?");
|
||||
return;
|
||||
}
|
||||
|
||||
xdg_shell_send_ping (xdg_shell, serial);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1781,16 +1548,3 @@ meta_wayland_surface_delete (MetaWaylandSurface *surface)
|
||||
if (surface->xdg_surface.resource)
|
||||
xdg_surface_send_delete (surface->xdg_surface.resource);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
if (surface->xdg_popup.resource)
|
||||
xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
|
||||
}
|
||||
|
@@ -75,6 +75,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
} MetaWaylandSurfaceExtension;
|
||||
|
||||
struct _MetaWaylandSurface
|
||||
@@ -85,7 +86,6 @@ struct _MetaWaylandSurface
|
||||
MetaWindow *window;
|
||||
MetaWaylandSurfaceExtension xdg_surface;
|
||||
MetaWaylandSurfaceExtension xdg_popup;
|
||||
MetaWaylandSurfaceExtension wl_shell_surface;
|
||||
MetaWaylandSurfaceExtension gtk_surface;
|
||||
MetaWaylandSurfaceExtension subsurface;
|
||||
|
||||
@@ -132,7 +132,4 @@ void meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
guint32 serial);
|
||||
void meta_wayland_surface_delete (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -37,7 +37,6 @@
|
||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||
#define META_WL_COMPOSITOR_VERSION 3
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
|
||||
#define META_WL_SHELL_VERSION 1
|
||||
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
|
||||
#define META_WL_OUTPUT_VERSION 2
|
||||
#define META_XSERVER_VERSION 1
|
||||
@@ -53,10 +52,9 @@
|
||||
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
|
||||
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
|
||||
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
|
||||
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
|
||||
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
|
||||
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */
|
||||
#define META_WL_SHELL_SURFACE_VERSION 1 /* from wl_shell */
|
||||
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
|
||||
#define META_WL_SUBSURFACE_VERSION 1 /* from wl_subcompositor */
|
||||
|
||||
/* The first version to implement a specific event */
|
||||
|
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_H
|
||||
#define META_WAYLAND_H
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
void meta_wayland_init (void);
|
||||
void meta_wayland_finalize (void);
|
||||
|
||||
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
|
||||
* API after meta_wayland_init() has been called. */
|
||||
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
|
||||
|
||||
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
int vt,
|
||||
GError **error);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user