diff --git a/12to11-test.xml b/12to11-test.xml
index 99fe3fd..5089fee 100644
--- a/12to11-test.xml
+++ b/12to11-test.xml
@@ -159,6 +159,17 @@
+
+
+
+ The activated is sent when the xdg_activation protocol causes
+ the surface associated with the role to be activated. Its
+ parameters constitute the timestamp at which the activation
+ occurred.
+
+
+
+
diff --git a/12to11.c b/12to11.c
index 8b275fe..3a40370 100644
--- a/12to11.c
+++ b/12to11.c
@@ -248,6 +248,7 @@ XLMain (int argc, char **argv)
XLInitKeyboardShortcutsInhibit ();
XLInitIdleInhibit ();
XLInitPointerGestures ();
+ XLInitXdgActivation ();
XLInitTest ();
/* This has to come after the rest of the initialization. */
diff --git a/Imakefile b/Imakefile
index 0f7a229..54456cc 100644
--- a/Imakefile
+++ b/Imakefile
@@ -18,8 +18,8 @@ MakeSubdirs($(SUBDIRS))
DependSubdirs($(SUBDIRS))
#endif
- SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c surface.c region.c shm.c atoms.c subcompositor.c positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c data_device.c xdg_popup.c dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c primary_selection.c renderer.c picture_renderer.c explicit_synchronization.c transform.c wp_viewporter.c decoration.c text_input.c single_pixel_buffer.c drm_lease.c pointer_constraints.c time.c relative_pointer.c keyboard_shortcuts_inhibit.c idle_inhibit.c process.c fence_ring.c pointer_gestures.c test.c buffer_release.c
- OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o surface.o region.o shm.o atoms.o subcompositor.o positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o data_device.o xdg_popup.o dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o primary_selection.o renderer.o picture_renderer.o explicit_synchronization.o transform.o wp_viewporter.o decoration.o text_input.o single_pixel_buffer.o drm_lease.o pointer_constraints.o time.o relative_pointer.o keyboard_shortcuts_inhibit.o idle_inhibit.o process.o fence_ring.o pointer_gestures.o test.o buffer_release.o
+ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c surface.c region.c shm.c atoms.c subcompositor.c positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c data_device.c xdg_popup.c dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c primary_selection.c renderer.c picture_renderer.c explicit_synchronization.c transform.c wp_viewporter.c decoration.c text_input.c single_pixel_buffer.c drm_lease.c pointer_constraints.c time.c relative_pointer.c keyboard_shortcuts_inhibit.c idle_inhibit.c process.c fence_ring.c pointer_gestures.c test.c buffer_release.c xdg_activation.c
+ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o surface.o region.o shm.o atoms.o subcompositor.o positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o data_device.o xdg_popup.o dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o primary_selection.o renderer.o picture_renderer.o explicit_synchronization.o transform.o wp_viewporter.o decoration.o text_input.o single_pixel_buffer.o drm_lease.o pointer_constraints.o time.o relative_pointer.o keyboard_shortcuts_inhibit.o idle_inhibit.o process.o fence_ring.o pointer_gestures.o test.o buffer_release.o xdg_activation.o
GENHEADERS = transfer_atoms.h drm_modifiers.h
HEADER = $(GENHEADERS) compositor.h
@@ -105,6 +105,7 @@ ScannerTarget(keyboard-shortcuts-inhibit-unstable-v1)
ScannerTarget(idle-inhibit-unstable-v1)
ScannerTarget(pointer-gestures-unstable-v1)
ScannerTarget(12to11-test)
+ScannerTarget(xdg-activation-v1)
/* Make seat.o depend on test_seat.c, as it includes that. Both files
are rather special. */
diff --git a/atoms.c b/atoms.c
index ea9028a..228e8f1 100644
--- a/atoms.c
+++ b/atoms.c
@@ -112,6 +112,7 @@ static const char *names[] =
"_NET_WM_PID",
"_NET_WM_PING",
"libinput Scrolling Pixel Distance",
+ "_NET_ACTIVE_WINDOW",
/* These are automatically generated from mime.txt. */
DirectTransferAtomNames
@@ -134,7 +135,8 @@ Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE, _NET_WM_SYNC_REQUEST_COUNTER,
XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished,
_NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND,
- CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING, libinput_Scrolling_Pixel_Distance;
+ CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING, libinput_Scrolling_Pixel_Distance,
+ _NET_ACTIVE_WINDOW;
XrmQuark resource_quark, app_quark, QString;
@@ -292,9 +294,10 @@ XLInitAtoms (void)
_NET_WM_PID = atoms[62];
_NET_WM_PING = atoms[63];
libinput_Scrolling_Pixel_Distance = atoms[64];
+ _NET_ACTIVE_WINDOW = atoms[65];
/* This is automatically generated. */
- DirectTransferAtomInit (atoms, 65);
+ DirectTransferAtomInit (atoms, 66);
/* Now, initialize quarks. */
resource_quark = XrmPermStringToQuark (compositor.resource_name);
diff --git a/compositor.h b/compositor.h
index bc4340f..7e742ab 100644
--- a/compositor.h
+++ b/compositor.h
@@ -1145,6 +1145,7 @@ struct _RoleFuncs
void (*select_extra_events) (Surface *, Role *, unsigned long);
void (*note_focus) (Surface *, Role *, FocusMode);
void (*outputs_changed) (Surface *, Role *);
+ void (*activate) (Surface *, Role *, int, Timestamp);
};
struct _Role
@@ -1238,7 +1239,8 @@ extern Atom _NET_WM_OPAQUE_REGION, _XL_BUFFER_RELEASE,
XdndProxy, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop,
XdndFinished, _NET_WM_FRAME_TIMINGS, _NET_WM_BYPASS_COMPOSITOR, WM_STATE,
_NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_MENU, _NET_WM_WINDOW_TYPE_DND,
- CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING, libinput_Scrolling_Pixel_Distance;
+ CONNECTOR_ID, _NET_WM_PID, _NET_WM_PING, libinput_Scrolling_Pixel_Distance,
+ _NET_ACTIVE_WINDOW;
extern XrmQuark resource_quark, app_quark, QString;
@@ -1340,6 +1342,7 @@ struct _XdgRoleImplementationFuncs
void (*note_focus) (Role *, XdgRoleImplementation *, FocusMode);
void (*outputs_changed) (Role *, XdgRoleImplementation *);
void (*after_commit) (Role *, Surface *, XdgRoleImplementation *);
+ void (*activate) (Role *, XdgRoleImplementation *, int, Time);
};
struct _XdgRoleImplementation
@@ -1616,6 +1619,7 @@ extern PinchGesture *XLSeatGetPinchGesture (Seat *, struct wl_resource *);
extern void XLSeatDestroySwipeGesture (SwipeGesture *);
extern void XLSeatDestroyPinchGesture (PinchGesture *);
extern KeyCode XLKeysymToKeycode (KeySym, XEvent *);
+extern Bool XLSeatCheckActivationSerial (Seat *, uint32_t);
extern Cursor InitDefaultCursor (void);
@@ -1857,6 +1861,10 @@ extern void ReleaseBufferWithHelper (BufferReleaseHelper *, ExtBuffer *,
extern void XLGetTestSeat (struct wl_client *, struct wl_resource *,
uint32_t);
+/* Defined in xdg_activation.c. */
+
+extern void XLInitXdgActivation (void);
+
/* Utility functions that don't belong in a specific file. */
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
diff --git a/seat.c b/seat.c
index a5f281b..05673eb 100644
--- a/seat.c
+++ b/seat.c
@@ -6387,6 +6387,20 @@ XLKeysymToKeycode (KeySym keysym, XEvent *event)
return 0;
}
+Bool
+XLSeatCheckActivationSerial (Seat *seat, uint32_t serial)
+{
+ /* Check if the specified serial can be used to activate surfaces on
+ behalf of seat. */
+
+ return ((seat->last_button_press_serial
+ && serial >= seat->last_button_press_serial)
+ || (seat->last_button_serial
+ && serial >= seat->last_button_press_serial)
+ || (seat->last_keyboard_serial
+ && serial >= seat->last_keyboard_serial));
+}
+
/* This is a particularly ugly hack, but there is no other way to
expose all the internals needed by test_seat.c. */
diff --git a/test.c b/test.c
index c27f669..c80af8b 100644
--- a/test.c
+++ b/test.c
@@ -336,6 +336,20 @@ GetWindow (Surface *surface, Role *role)
return test->window;
}
+static void
+Activate (Surface *surface, Role *role, int deviceid,
+ Timestamp timestamp)
+{
+ TestSurface *test;
+
+ test = TestSurfaceFromRole (role);
+
+ if (test->role.resource)
+ test_surface_send_activated (test->role.resource,
+ timestamp.months,
+ timestamp.milliseconds);
+}
+
static const struct test_surface_interface test_surface_impl =
{
.destroy = Destroy,
@@ -489,6 +503,7 @@ GetTestSurface (struct wl_client *client, struct wl_resource *resource,
test->role.funcs.release_buffer = ReleaseBuffer;
test->role.funcs.subsurface_update = SubsurfaceUpdate;
test->role.funcs.get_window = GetWindow;
+ test->role.funcs.activate = Activate;
/* Add the resource implementation. */
wl_resource_set_implementation (test->role.resource, &test_surface_impl,
diff --git a/tests/Imakefile b/tests/Imakefile
index fb4ad0d..7d2d81d 100644
--- a/tests/Imakefile
+++ b/tests/Imakefile
@@ -26,6 +26,7 @@ name.c: $(12TO11ROOT)/name.xml name.h @@\
ScannerTarget(12to11-test)
ScannerTarget(viewporter)
ScannerTarget(linux-dmabuf-unstable-v1)
+ScannerTarget(xdg-activation-v1)
/* Not actually a test. */
SRCS1 = $(COMMONSRCS) imgview.c
@@ -52,7 +53,9 @@ ScannerTarget(linux-dmabuf-unstable-v1)
OBJS11 = select_helper.o
SRCS12 = select_helper_multiple.c
OBJS12 = select_helper_multiple.o
- PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper select_helper_multiple
+ SRCS13 = $(COMMONSRCS) xdg_activation_test.c
+ OBJS13 = $(COMMONSRCS) xdg_activation_test.o
+ PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper select_helper_multiple xdg_activation_test
/* Make all objects depend on HEADER. */
$(OBJS1): $(HEADER)
@@ -72,10 +75,12 @@ NormalProgramTarget(dmabuf_test,$(OBJS9),NullParameter,$(LOCAL_LIBRARIES) $(GBM)
NormalProgramTarget(select_test,$(OBJS10),NullParameter,$(LOCAL_LIBRARIES) ThreadsLibraries,NullParameter);
NormalProgramTarget(select_helper,$(OBJS11),NullParameter,$(XLIB),NullParameter);
NormalProgramTarget(select_helper_multiple,$(OBJS12),NullParameter,$(XLIB),NullParameter);
+NormalProgramTarget(xdg_activation_test,$(OBJS13),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
DependTarget3($(SRCS1),$(SRCS2),$(SRCS3))
DependTarget3($(SRCS4),$(SRCS5),$(SRCS6))
DependTarget3($(SRCS7),$(SRCS8),$(SRCS9))
DependTarget3($(SRCS10),$(SRCS11),$(SRCS12))
+DependTarget3($(SRCS13),NullParameter,NullParameter)
all:: $(PROGRAMS)
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index bdd4572..d171c46 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -22,6 +22,7 @@ pushd "$(dirname $0)"
declare -a standard_tests=(
simple_test damage_test transform_test viewporter_test
subsurface_test scale_test seat_test dmabuf_test
+ xdg_activation_test
)
make -C . "${standard_tests[@]}"
diff --git a/tests/svnignore.txt b/tests/svnignore.txt
index 246cf29..8fe643c 100644
--- a/tests/svnignore.txt
+++ b/tests/svnignore.txt
@@ -12,6 +12,7 @@ dmabuf_test
select_test
select_helper
select_helper_multiple
+xdg_activation_test
imgview
reject.dump
Makefile
diff --git a/xdg_surface.c b/xdg_surface.c
index ca22c22..6f8a205 100644
--- a/xdg_surface.c
+++ b/xdg_surface.c
@@ -1392,6 +1392,20 @@ OutputsChanged (Surface *surface, Role *role)
xdg_role->impl->funcs.outputs_changed (role, xdg_role->impl);
}
+static void
+Activate (Surface *surface, Role *role, int deviceid,
+ Timestamp timestamp)
+{
+ XdgRole *xdg_role;
+
+ xdg_role = XdgRoleFromRole (role);
+
+ if (xdg_role->impl && xdg_role->impl->funcs.activate)
+ xdg_role->impl->funcs.activate (role, xdg_role->impl,
+ deviceid,
+ timestamp.milliseconds);
+}
+
void
XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
uint32_t id, struct wl_resource *surface_resource)
@@ -1464,6 +1478,7 @@ XLGetXdgSurface (struct wl_client *client, struct wl_resource *resource,
role->role.funcs.select_extra_events = SelectExtraEvents;
role->role.funcs.note_focus = NoteFocus;
role->role.funcs.outputs_changed = OutputsChanged;
+ role->role.funcs.activate = Activate;
attrs.colormap = compositor.colormap;
attrs.border_pixel = border_pixel;
diff --git a/xdg_toplevel.c b/xdg_toplevel.c
index fc9a1a1..234c992 100644
--- a/xdg_toplevel.c
+++ b/xdg_toplevel.c
@@ -31,6 +31,8 @@ along with 12to11. If not, see . */
#include "xdg-shell.h"
#include "xdg-decoration-unstable-v1.h"
+#include
+
#define ToplevelFromRoleImpl(impl) ((XdgToplevel *) (impl))
typedef struct _XdgToplevel XdgToplevel;
@@ -2253,6 +2255,49 @@ OutputsChanged (Role *role, XdgRoleImplementation *impl)
}
}
+static void
+Activate (Role *role, XdgRoleImplementation *impl, int deviceid,
+ Time time)
+{
+ XEvent message;
+ XdgToplevel *toplevel;
+ Window window;
+
+ toplevel = ToplevelFromRoleImpl (impl);
+ window = XLWindowFromXdgRole (toplevel->role);
+
+ if (XLWmSupportsHint (_NET_ACTIVE_WINDOW))
+ {
+ /* Use a _NET_ACTIVE_WINDOW request. */
+ message.xclient.type = ClientMessage;
+ message.xclient.window = window;
+ message.xclient.message_type = _NET_ACTIVE_WINDOW;
+ message.xclient.format = 32;
+ message.xclient.data.l[0] = 1;
+ message.xclient.data.l[1] = time;
+ message.xclient.data.l[2] = None;
+ message.xclient.data.l[3] = 0;
+ message.xclient.data.l[4] = 0;
+
+ fprintf (stderr, "activate at: %d\n", (int) time);
+
+ XSendEvent (compositor.display,
+ DefaultRootWindow (compositor.display),
+ False, (SubstructureRedirectMask
+ | SubstructureNotifyMask),
+ &message);
+ }
+ else
+ {
+ /* Catch errors as we cannot be sure that the window is viewable
+ or that the device still exists. */
+ CatchXErrors ();
+ XISetFocus (compositor.display, deviceid,
+ window, time);
+ UncatchXErrors (NULL);
+ }
+}
+
static const struct xdg_toplevel_interface xdg_toplevel_impl =
{
.destroy = Destroy,
@@ -2319,6 +2364,7 @@ XLGetXdgToplevel (struct wl_client *client, struct wl_resource *resource,
toplevel->impl.funcs.is_window_mapped = IsWindowMapped;
toplevel->impl.funcs.outputs_changed = OutputsChanged;
toplevel->impl.funcs.after_commit = AfterCommit;
+ toplevel->impl.funcs.activate = Activate;
if (!XLWmSupportsHint (_NET_WM_STATE_FOCUSED))
/* If _NET_WM_STATE_FOCUSED is unsupported, fall back to utilizing