diff --git a/sway/criteria.c b/sway/criteria.c
index 04683f66..9a04b48e 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -12,9 +12,12 @@
 
 enum criteria_type { // *must* keep in sync with criteria_strings[]
 	CRIT_CLASS,
+	CRIT_CON_ID,
 	CRIT_CON_MARK,
+	CRIT_FLOATING,
 	CRIT_ID,
 	CRIT_INSTANCE,
+	CRIT_TILING,
 	CRIT_TITLE,
 	CRIT_URGENT,
 	CRIT_WINDOW_ROLE,
@@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
 
 static const char * const criteria_strings[CRIT_LAST] = {
 	[CRIT_CLASS] = "class",
+	[CRIT_CON_ID] = "con_id",
 	[CRIT_CON_MARK] = "con_mark",
+	[CRIT_FLOATING] = "floating",
 	[CRIT_ID] = "id",
 	[CRIT_INSTANCE] = "instance",
+	[CRIT_TILING] = "tiling",
 	[CRIT_TITLE] = "title",
 	[CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
 	[CRIT_WINDOW_ROLE] = "window_role",
@@ -263,6 +269,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
 				matches++;
 			}
 			break;
+		case CRIT_CON_ID: {
+			char *endptr;
+			size_t crit_id = strtoul(crit->raw, &endptr, 10);
+
+			if (*endptr == 0 && cont->id == crit_id) {
+				++matches;
+			}
+			break;
+		}
 		case CRIT_CON_MARK:
 			if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
 				// Make sure it isn't matching the NUL string
@@ -271,6 +286,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
 				}
 			}
 			break;
+		case CRIT_FLOATING:
+			if (cont->is_floating) {
+				matches++;
+			}
+			break;
 		case CRIT_ID:
 			if (!cont->app_id) {
 				// ignore
@@ -290,6 +310,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
 				matches++;
 			}
 			break;
+		case CRIT_TILING:
+			if (!cont->is_floating) {
+				matches++;
+			}
+			break;
 		case CRIT_TITLE:
 			if (!cont->name) {
 				// ignore