Index: uspace/lib/ui/include/types/ui/event.h
===================================================================
--- uspace/lib/ui/include/types/ui/event.h	(revision a2f173be0f2c6ba06f576d61326899b73d022e05)
+++ uspace/lib/ui/include/types/ui/event.h	(revision a2f173be0f2c6ba06f576d61326899b73d022e05)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libui
+ * @{
+ */
+/**
+ * @file Event
+ */
+
+#ifndef _UI_TYPES_EVENT_H
+#define _UI_TYPES_EVENT_H
+
+/** Event claim.
+ *
+ * This type is returned by an event processing function to signal whether
+ * it ruled that the event is destined for it or not
+ */
+typedef enum {
+	/** Event claimed */
+	ui_claimed,
+	/** Event not claimed */
+	ui_unclaimed
+} ui_evclaim_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ui/include/ui/pbutton.h
===================================================================
--- uspace/lib/ui/include/ui/pbutton.h	(revision 172188a438435269d832f06a54186d03a955efe5)
+++ uspace/lib/ui/include/ui/pbutton.h	(revision a2f173be0f2c6ba06f576d61326899b73d022e05)
@@ -40,4 +40,5 @@
 #include <gfx/coord.h>
 #include <io/pos_event.h>
+#include <types/ui/event.h>
 #include <types/ui/pbutton.h>
 #include <types/ui/resource.h>
@@ -56,5 +57,5 @@
 extern void ui_pbutton_leave(ui_pbutton_t *);
 extern void ui_pbutton_clicked(ui_pbutton_t *);
-extern void ui_pbutton_pos_event(ui_pbutton_t *, pos_event_t *);
+extern ui_evclaim_t ui_pbutton_pos_event(ui_pbutton_t *, pos_event_t *);
 
 #endif
Index: uspace/lib/ui/src/pbutton.c
===================================================================
--- uspace/lib/ui/src/pbutton.c	(revision 172188a438435269d832f06a54186d03a955efe5)
+++ uspace/lib/ui/src/pbutton.c	(revision a2f173be0f2c6ba06f576d61326899b73d022e05)
@@ -350,6 +350,7 @@
  * @param pbutton Push button
  * @param pos_event Position event
- */
-void ui_pbutton_pos_event(ui_pbutton_t *pbutton, pos_event_t *event)
+ * @return @c ui_claimed iff the event is claimed
+ */
+ui_evclaim_t ui_pbutton_pos_event(ui_pbutton_t *pbutton, pos_event_t *event)
 {
 	gfx_coord2_t pos;
@@ -363,13 +364,19 @@
 	switch (event->type) {
 	case POS_PRESS:
-		if (inside)
+		if (inside) {
 			ui_pbutton_press(pbutton);
+			return ui_claimed;
+		}
 		break;
 	case POS_RELEASE:
-		ui_pbutton_release(pbutton);
+		if (pbutton->held) {
+			ui_pbutton_release(pbutton);
+			return ui_claimed;
+		}
 		break;
 	case POS_UPDATE:
 		if (inside && !pbutton->inside) {
 			ui_pbutton_enter(pbutton);
+			return ui_claimed;
 		} else if (!inside && pbutton->inside) {
 			ui_pbutton_leave(pbutton);
@@ -377,4 +384,6 @@
 		break;
 	}
+
+	return ui_unclaimed;
 }
 
Index: uspace/lib/ui/src/wdecor.c
===================================================================
--- uspace/lib/ui/src/wdecor.c	(revision 172188a438435269d832f06a54186d03a955efe5)
+++ uspace/lib/ui/src/wdecor.c	(revision a2f173be0f2c6ba06f576d61326899b73d022e05)
@@ -280,4 +280,5 @@
 	gfx_coord2_t pos;
 	ui_wdecor_geom_t geom;
+	ui_evclaim_t claim;
 
 	pos.x = event->hpos;
@@ -286,8 +287,7 @@
 	ui_wdecor_get_geom(wdecor, &geom);
 
-	if (gfx_pix_inside_rect(&pos, &geom.btn_close_rect)) {
-		ui_pbutton_pos_event(wdecor->btn_close, event);
+	claim = ui_pbutton_pos_event(wdecor->btn_close, event);
+	if (claim == ui_claimed)
 		return;
-	}
 
 	if (event->type == POS_PRESS &&
Index: uspace/lib/ui/test/pbutton.c
===================================================================
--- uspace/lib/ui/test/pbutton.c	(revision 172188a438435269d832f06a54186d03a955efe5)
+++ uspace/lib/ui/test/pbutton.c	(revision a2f173be0f2c6ba06f576d61326899b73d022e05)
@@ -359,4 +359,5 @@
 	ui_resource_t *resource = NULL;
 	ui_pbutton_t *pbutton;
+	ui_evclaim_t claim;
 	pos_event_t event;
 	gfx_rect_t rect;
@@ -381,24 +382,27 @@
 	ui_pbutton_set_rect(pbutton, &rect);
 
-	/* Press outside does nothing */
+	/* Press outside is not claimed and does nothing */
 	event.type = POS_PRESS;
 	event.hpos = 9;
 	event.vpos = 20;
-	ui_pbutton_pos_event(pbutton, &event);
-	PCUT_ASSERT_FALSE(pbutton->held);
-
-	/* Press inside depresses button */
+	claim = ui_pbutton_pos_event(pbutton, &event);
+	PCUT_ASSERT_FALSE(pbutton->held);
+	PCUT_ASSERT_EQUALS(ui_unclaimed, claim);
+
+	/* Press inside is claimed and depresses button */
 	event.type = POS_PRESS;
 	event.hpos = 10;
 	event.vpos = 20;
-	ui_pbutton_pos_event(pbutton, &event);
-	PCUT_ASSERT_TRUE(pbutton->held);
-
-	/* Release outside (or anywhere) relases button */
+	claim = ui_pbutton_pos_event(pbutton, &event);
+	PCUT_ASSERT_TRUE(pbutton->held);
+	PCUT_ASSERT_EQUALS(ui_claimed, claim);
+
+	/* Release outside (or anywhere) is claimed and relases button */
 	event.type = POS_RELEASE;
 	event.hpos = 9;
 	event.vpos = 20;
-	ui_pbutton_pos_event(pbutton, &event);
-	PCUT_ASSERT_FALSE(pbutton->held);
+	claim = ui_pbutton_pos_event(pbutton, &event);
+	PCUT_ASSERT_FALSE(pbutton->held);
+	PCUT_ASSERT_EQUALS(ui_claimed, claim);
 
 	ui_pbutton_destroy(pbutton);
