diff --git a/include/sway/input.h b/include/sway/input.h
index 4ed9bffe..eb92e470 100644
--- a/include/sway/input.h
+++ b/include/sway/input.h
@@ -1,18 +1,19 @@
 #ifndef _SWAY_INPUT_H
 #define _SWAY_INPUT_H
-
 #include <libinput.h>
+#include "sway/server.h"
 #include "config.h"
 #include "list.h"
 
+struct sway_input {
+	list_t *input_devices;
+};
+
 struct input_config *new_input_config(const char* identifier);
 
 char* libinput_dev_unique_id(struct libinput_device *dev);
 
-/**
- * Global input device list.
- */
-extern list_t *input_devices;
+struct sway_input *sway_input_create(struct sway_server *server);
 
 /**
  * Pointer used when reading input blocked.
diff --git a/include/sway/server.h b/include/sway/server.h
index 9cd760ac..22069f9c 100644
--- a/include/sway/server.h
+++ b/include/sway/server.h
@@ -10,9 +10,6 @@
 #include <wlr/xwayland.h>
 
 struct sway_server {
-	// TODO WLR
-	//struct roots_input *input;
-
 	struct wl_display *wl_display;
 	struct wl_event_loop *wl_event_loop;
 
@@ -20,6 +17,8 @@ struct sway_server {
 	struct wlr_renderer *renderer;
 
 	struct wlr_data_device_manager *data_device_manager;
+
+	struct sway_input *input;
 };
 
 bool server_init(struct sway_server *server);
diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt
index ac0530e5..3c78aec9 100644
--- a/sway/CMakeLists.txt
+++ b/sway/CMakeLists.txt
@@ -26,7 +26,6 @@ add_executable(sway
 	criteria.c
 	debug_log.c
 	focus.c
-	input.c
 	input_state.c
 	ipc-json.c
 	ipc-server.c
@@ -37,6 +36,8 @@ add_executable(sway
 	border.c
 	security.c
     server.c
+
+	input/input.c
 )
 
 add_definitions(
diff --git a/sway/input.c b/sway/input/input.c
similarity index 89%
rename from sway/input.c
rename to sway/input/input.c
index 6263f79f..02b4995e 100644
--- a/sway/input.c
+++ b/sway/input/input.c
@@ -7,9 +7,20 @@
 #include <libinput.h>
 #include "sway/config.h"
 #include "sway/input.h"
+#include "sway/server.h"
 #include "list.h"
 #include "log.h"
 
+struct input_config *current_input_config = NULL;
+
+struct sway_input *sway_input_create(struct sway_server *server) {
+	struct sway_input *input = calloc(1, sizeof(struct sway_input));
+	if (!input) {
+		return NULL;
+	}
+	return input;
+}
+
 struct input_config *new_input_config(const char* identifier) {
 	struct input_config *input = calloc(1, sizeof(struct input_config));
 	if (!input) {
@@ -64,6 +75,3 @@ char *libinput_dev_unique_id(struct libinput_device *device) {
 	free(name);
 	return identifier;
 }
-
-list_t *input_devices = NULL;
-struct input_config *current_input_config = NULL;
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 9ba736d8..d4db4e7a 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -476,12 +476,14 @@ void ipc_client_handle_command(struct ipc_client *client) {
 			goto exit_denied;
 		}
 		json_object *inputs = json_object_new_array();
+		/* TODO WLR
 		if (input_devices) {
 			for(int i = 0; i<input_devices->length; i++) {
 				struct libinput_device *device = input_devices->items[i];
 				json_object_array_add(inputs, ipc_json_describe_input(device));
 			}
 		}
+		*/
 		const char *json_string = json_object_to_json_string(inputs);
 		ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 		json_object_put(inputs);
diff --git a/sway/server.c b/sway/server.c
index 39fa5d28..4a74cfb5 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -10,6 +10,7 @@
 // TODO WLR: make Xwayland optional
 #include <wlr/xwayland.h>
 #include "sway/server.h"
+#include "sway/input.h"
 #include "log.h"
 
 bool server_init(struct sway_server *server) {
@@ -22,9 +23,7 @@ bool server_init(struct sway_server *server) {
 	server->renderer = wlr_gles2_renderer_create(server->backend);
 	wl_display_init_shm(server->wl_display);
 
-	// TODO WLR
-	//server->desktop = desktop_create(server, server.config);
-	//server->input = input_create(&server, server.config);
+	server->input = sway_input_create(server);
 	server->data_device_manager =
 		wlr_data_device_manager_create(server->wl_display);