mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge branch 'master' of https://github.com/SirCmpwn/sway
This commit is contained in:
		
						commit
						5a9ba261bc
					
				
					 26 changed files with 1493 additions and 570 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -9,3 +9,4 @@ bin/
 | 
				
			||||||
test/
 | 
					test/
 | 
				
			||||||
build/
 | 
					build/
 | 
				
			||||||
.lvimrc
 | 
					.lvimrc
 | 
				
			||||||
 | 
					config-debug
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@ project(sway C)
 | 
				
			||||||
set(CMAKE_C_FLAGS "-g")
 | 
					set(CMAKE_C_FLAGS "-g")
 | 
				
			||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/")
 | 
					set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/")
 | 
				
			||||||
add_definitions("-Wall")
 | 
					add_definitions("-Wall")
 | 
				
			||||||
set(CMAKE_BUILD_TYPE Debug)
 | 
					 | 
				
			||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMake)
 | 
					set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMake)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
find_package(XKBCommon REQUIRED)
 | 
					find_package(XKBCommon REQUIRED)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,9 +41,12 @@ struct sway_config {
 | 
				
			||||||
	bool active;
 | 
						bool active;
 | 
				
			||||||
	bool failed;
 | 
						bool failed;
 | 
				
			||||||
	bool reloading;
 | 
						bool reloading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int gaps_inner;
 | 
				
			||||||
 | 
						int gaps_outer;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool load_config(void);
 | 
					bool load_config(const char *file);
 | 
				
			||||||
bool read_config(FILE *file, bool is_active);
 | 
					bool read_config(FILE *file, bool is_active);
 | 
				
			||||||
char *do_var_replacement(struct sway_config *config, char *str);
 | 
					char *do_var_replacement(struct sway_config *config, char *str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ enum swayc_types{
 | 
				
			||||||
	C_WORKSPACE,
 | 
						C_WORKSPACE,
 | 
				
			||||||
	C_CONTAINER,
 | 
						C_CONTAINER,
 | 
				
			||||||
	C_VIEW,
 | 
						C_VIEW,
 | 
				
			||||||
	//Keep last
 | 
						// Keep last
 | 
				
			||||||
	C_TYPES,
 | 
						C_TYPES,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ enum swayc_layouts{
 | 
				
			||||||
	L_STACKED,
 | 
						L_STACKED,
 | 
				
			||||||
	L_TABBED,
 | 
						L_TABBED,
 | 
				
			||||||
	L_FLOATING,
 | 
						L_FLOATING,
 | 
				
			||||||
	//Keep last
 | 
						// Keep last
 | 
				
			||||||
	L_LAYOUTS,
 | 
						L_LAYOUTS,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,10 +45,10 @@ struct sway_container {
 | 
				
			||||||
	bool is_floating;
 | 
						bool is_floating;
 | 
				
			||||||
	bool is_focused;
 | 
						bool is_focused;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int weight;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int gaps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_t *children;
 | 
						list_t *children;
 | 
				
			||||||
	list_t *floating;
 | 
						list_t *floating;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,7 @@ struct sway_container {
 | 
				
			||||||
	struct sway_container *focused;
 | 
						struct sway_container *focused;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Container Creation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *new_output(wlc_handle handle);
 | 
					swayc_t *new_output(wlc_handle handle);
 | 
				
			||||||
swayc_t *new_workspace(swayc_t *output, const char *name);
 | 
					swayc_t *new_workspace(swayc_t *output, const char *name);
 | 
				
			||||||
| 
						 | 
					@ -66,18 +67,29 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle);
 | 
				
			||||||
// Creates view as a new floating view which is in the active workspace
 | 
					// Creates view as a new floating view which is in the active workspace
 | 
				
			||||||
swayc_t *new_floating_view(wlc_handle handle);
 | 
					swayc_t *new_floating_view(wlc_handle handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Container Destroying
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *destroy_output(swayc_t *output);
 | 
					swayc_t *destroy_output(swayc_t *output);
 | 
				
			||||||
// Destroys workspace if empty and returns parent pointer, else returns NULL
 | 
					// Destroys workspace if empty and returns parent pointer, else returns NULL
 | 
				
			||||||
swayc_t *destroy_workspace(swayc_t *workspace);
 | 
					swayc_t *destroy_workspace(swayc_t *workspace);
 | 
				
			||||||
 | 
					// Destroyes container and all parent container if they are empty, returns
 | 
				
			||||||
 | 
					// topmost non-empty parent. returns NULL otherwise
 | 
				
			||||||
swayc_t *destroy_container(swayc_t *container);
 | 
					swayc_t *destroy_container(swayc_t *container);
 | 
				
			||||||
 | 
					// Destroys view and all empty parent containers. return topmost non-empty
 | 
				
			||||||
 | 
					// parent
 | 
				
			||||||
swayc_t *destroy_view(swayc_t *view);
 | 
					swayc_t *destroy_view(swayc_t *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Container Lookup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types);
 | 
				
			||||||
 | 
					swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data);
 | 
					swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data);
 | 
				
			||||||
void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *);
 | 
					void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Mappings
 | 
					// Mappings
 | 
				
			||||||
void set_view_visibility(swayc_t *view, void *data);
 | 
					void set_view_visibility(swayc_t *view, void *data);
 | 
				
			||||||
 | 
					void reset_gaps(swayc_t *view, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,5 @@
 | 
				
			||||||
#ifndef _SWAY_FOCUS_H
 | 
					#ifndef _SWAY_FOCUS_H
 | 
				
			||||||
#define _SWAY_FOCUS_H
 | 
					#define _SWAY_FOCUS_H
 | 
				
			||||||
#include "container.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum movement_direction {
 | 
					enum movement_direction {
 | 
				
			||||||
	MOVE_LEFT,
 | 
						MOVE_LEFT,
 | 
				
			||||||
	MOVE_RIGHT,
 | 
						MOVE_RIGHT,
 | 
				
			||||||
| 
						 | 
					@ -10,6 +8,8 @@ enum movement_direction {
 | 
				
			||||||
	MOVE_PARENT
 | 
						MOVE_PARENT
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// focused_container - the container found by following the `focused` pointer
 | 
					// focused_container - the container found by following the `focused` pointer
 | 
				
			||||||
// from a given container to a container with `is_focused` boolean set
 | 
					// from a given container to a container with `is_focused` boolean set
 | 
				
			||||||
// ---
 | 
					// ---
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								include/input_state.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								include/input_state.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					#ifndef  _SWAY_KEY_STATE_H
 | 
				
			||||||
 | 
					#define  _SWAY_KEY_STATE_H
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include "container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Keyboard state */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef uint32_t keycode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// returns true if key has been pressed, otherwise false
 | 
				
			||||||
 | 
					bool check_key(keycode key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// sets a key as pressed
 | 
				
			||||||
 | 
					void press_key(keycode key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// unsets a key as pressed
 | 
				
			||||||
 | 
					void release_key(keycode key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Pointer state */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum pointer_values {
 | 
				
			||||||
 | 
						M_LEFT_CLICK = 272,
 | 
				
			||||||
 | 
						M_RIGHT_CLICK = 273,
 | 
				
			||||||
 | 
						M_SCROLL_CLICK = 274,
 | 
				
			||||||
 | 
						M_SCROLL_UP = 275,
 | 
				
			||||||
 | 
						M_SCROLL_DOWN = 276,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct pointer_state {
 | 
				
			||||||
 | 
						bool l_held;
 | 
				
			||||||
 | 
						bool r_held;
 | 
				
			||||||
 | 
						struct pointer_floating {
 | 
				
			||||||
 | 
							bool drag;
 | 
				
			||||||
 | 
							bool resize;
 | 
				
			||||||
 | 
						} floating;
 | 
				
			||||||
 | 
						struct pointer_lock {
 | 
				
			||||||
 | 
							bool left;
 | 
				
			||||||
 | 
							bool right;
 | 
				
			||||||
 | 
							bool top;
 | 
				
			||||||
 | 
							bool bottom;
 | 
				
			||||||
 | 
						} lock;
 | 
				
			||||||
 | 
					} pointer_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void start_floating(swayc_t *view);
 | 
				
			||||||
 | 
					void reset_floating(swayc_t *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								include/ipc.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								include/ipc.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					#ifndef _SWAY_IPC_H
 | 
				
			||||||
 | 
					#define _SWAY_IPC_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum ipc_command_type {
 | 
				
			||||||
 | 
						IPC_COMMAND        = 0,
 | 
				
			||||||
 | 
						IPC_GET_WORKSPACES = 1,
 | 
				
			||||||
 | 
						IPC_SUBSCRIBE      = 2,
 | 
				
			||||||
 | 
						IPC_GET_OUTPUTS    = 3,
 | 
				
			||||||
 | 
						IPC_GET_TREE       = 4,
 | 
				
			||||||
 | 
						IPC_GET_MARKS      = 5,
 | 
				
			||||||
 | 
						IPC_GET_BAR_CONFIG = 6,
 | 
				
			||||||
 | 
						IPC_GET_VERSION    = 7,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_init(void);
 | 
				
			||||||
 | 
					void ipc_terminate(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -4,12 +4,14 @@
 | 
				
			||||||
#include <wlc/wlc.h>
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include "container.h"
 | 
					#include "container.h"
 | 
				
			||||||
 | 
					#include "focus.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern swayc_t root_container;
 | 
					extern swayc_t root_container;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void init_layout(void);
 | 
					void init_layout(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void add_child(swayc_t *parent, swayc_t *child);
 | 
					void add_child(swayc_t *parent, swayc_t *child);
 | 
				
			||||||
 | 
					void add_floating(swayc_t *ws, swayc_t *child);
 | 
				
			||||||
// Returns parent container which needs to be rearranged.
 | 
					// Returns parent container which needs to be rearranged.
 | 
				
			||||||
swayc_t *add_sibling(swayc_t *sibling, swayc_t *child);
 | 
					swayc_t *add_sibling(swayc_t *sibling, swayc_t *child);
 | 
				
			||||||
swayc_t *replace_child(swayc_t *child, swayc_t *new_child);
 | 
					swayc_t *replace_child(swayc_t *child, swayc_t *new_child);
 | 
				
			||||||
| 
						 | 
					@ -28,5 +30,6 @@ void focus_view_for(swayc_t *ancestor, swayc_t *container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *get_focused_container(swayc_t *parent);
 | 
					swayc_t *get_focused_container(swayc_t *parent);
 | 
				
			||||||
swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent);
 | 
					swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent);
 | 
				
			||||||
 | 
					swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
#ifndef _SWAY_LOG_H
 | 
					#ifndef _SWAY_LOG_H
 | 
				
			||||||
#define _SWAY_LOG_H
 | 
					#define _SWAY_LOG_H
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include "container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
	L_SILENT = 0,
 | 
						L_SILENT = 0,
 | 
				
			||||||
| 
						 | 
					@ -10,7 +12,10 @@ typedef enum {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void init_log(int verbosity);
 | 
					void init_log(int verbosity);
 | 
				
			||||||
void sway_log_colors(int mode);
 | 
					void sway_log_colors(int mode);
 | 
				
			||||||
void sway_log(int verbosity, char* format, ...) __attribute__((format(printf,2,3)));
 | 
					void sway_log(int verbosity, const char* format, ...) __attribute__((format(printf,2,3)));
 | 
				
			||||||
void sway_abort(char* format, ...)__attribute__((format(printf,1,2)));
 | 
					void sway_log_errno(int verbosity, char* format, ...) __attribute__((format(printf,2,3)));
 | 
				
			||||||
 | 
					void sway_abort(const char* format, ...) __attribute__((format(printf,1,2)));
 | 
				
			||||||
 | 
					bool sway_assert(bool condition, const char* format, ...) __attribute__((format(printf,2,3)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void layout_log(const swayc_t *c, int depth);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,5 +10,6 @@ char *code_strchr(const char *string, char delimiter);
 | 
				
			||||||
char *code_strstr(const char *haystack, const char *needle);
 | 
					char *code_strstr(const char *haystack, const char *needle);
 | 
				
			||||||
int unescape_string(char *string);
 | 
					int unescape_string(char *string);
 | 
				
			||||||
char *join_args(char **argv, int argc);
 | 
					char *join_args(char **argv, int argc);
 | 
				
			||||||
 | 
					char *join_list(list_t *list, char *separator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								include/sway.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								include/sway.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					#ifndef _SWAY_SWAY_H
 | 
				
			||||||
 | 
					#define _SWAY_SWAY_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sway_terminate(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,5 @@ void workspace_output_next();
 | 
				
			||||||
void workspace_next();
 | 
					void workspace_next();
 | 
				
			||||||
void workspace_output_prev();
 | 
					void workspace_output_prev();
 | 
				
			||||||
void workspace_prev();
 | 
					void workspace_prev();
 | 
				
			||||||
void layout_log(const swayc_t *c, int depth);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										30
									
								
								sway.5.txt
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								sway.5.txt
									
										
									
									
									
								
							| 
						 | 
					@ -22,11 +22,11 @@ Commands
 | 
				
			||||||
--------
 | 
					--------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**bindsym** <key combo> <command>::
 | 
					**bindsym** <key combo> <command>::
 | 
				
			||||||
	Binds _key combo_ to execute _command_ when pressed. You may use XKB key names
 | 
						Binds _key combo_ to execute _command_ when pressed. You may use XKB key
 | 
				
			||||||
	here (**xev**(1) is a good tool for discovering them). An example bindsym
 | 
						names here (**xev**(1) is a good tool for discovering them). An example
 | 
				
			||||||
	command would be _bindsym Mod1+Shift+f exec firefox_, which would execute
 | 
						bindsym command would be _bindsym Mod1+Shift+f exec firefox_, which would
 | 
				
			||||||
	Firefox if the alt, shift, and F keys are pressed together. Any valid sway
 | 
						execute Firefox if the alt, shift, and F keys are pressed together. Any
 | 
				
			||||||
	command is eligible to be bound to a key combo.
 | 
						valid sway command is eligible to be bound to a key combo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**exec** <shell command>::
 | 
					**exec** <shell command>::
 | 
				
			||||||
	Executes _shell command_ with sh.
 | 
						Executes _shell command_ with sh.
 | 
				
			||||||
| 
						 | 
					@ -48,6 +48,9 @@ Commands
 | 
				
			||||||
	container, which is useful, for example, to open a sibling of the parent
 | 
						container, which is useful, for example, to open a sibling of the parent
 | 
				
			||||||
	container, or to move the entire container around.
 | 
						container, or to move the entire container around.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**focus** mode_toggle::
 | 
				
			||||||
 | 
						Toggles focus between floating view and tiled view.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**focus_follows_mouse** <yes|no>::
 | 
					**focus_follows_mouse** <yes|no>::
 | 
				
			||||||
	If set to _yes_, the currently focused view will change as you move your
 | 
						If set to _yes_, the currently focused view will change as you move your
 | 
				
			||||||
	mouse around the screen to the view that ends up underneath your mouse.
 | 
						mouse around the screen to the view that ends up underneath your mouse.
 | 
				
			||||||
| 
						 | 
					@ -76,13 +79,24 @@ Commands
 | 
				
			||||||
**splitv**::
 | 
					**splitv**::
 | 
				
			||||||
	Equivalent to **split vertical**.
 | 
						Equivalent to **split vertical**.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**fullscreen**:
 | 
					**floating_modifier** <modifier>::
 | 
				
			||||||
 | 
						When the _modifier_ key is held down, you may use left click to drag floating
 | 
				
			||||||
 | 
						windows, and right click to resize them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**fullscreen**::
 | 
				
			||||||
	Toggles fullscreen status for the focused view.
 | 
						Toggles fullscreen status for the focused view.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**workspace** <name>:
 | 
					**gaps** <amount>::
 | 
				
			||||||
 | 
						Adds _amount_ pixels between each view, and around each output.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**gaps** <inner|outer> <amount>::
 | 
				
			||||||
 | 
						Adds _amount_ pixels as an _inner_ or _outer_ gap, where the former affects
 | 
				
			||||||
 | 
						spacing between views and the latter affects the space around each output.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**workspace** <name>::
 | 
				
			||||||
	Switches to the specified workspace.
 | 
						Switches to the specified workspace.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**workspace** <prev_on_output|next_on_output>:
 | 
					**workspace** <prev_on_output|next_on_output>::
 | 
				
			||||||
	Switches to the next workspace on the current output.
 | 
						Switches to the next workspace on the current output.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**workspace** <name> output <output>::
 | 
					**workspace** <name> output <output>::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										186
									
								
								sway/commands.c
									
										
									
									
									
								
							
							
						
						
									
										186
									
								
								sway/commands.c
									
										
									
									
									
								
							| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include <wlc/wlc.h>
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
| 
						 | 
					@ -14,6 +15,7 @@
 | 
				
			||||||
#include "commands.h"
 | 
					#include "commands.h"
 | 
				
			||||||
#include "container.h"
 | 
					#include "container.h"
 | 
				
			||||||
#include "handlers.h"
 | 
					#include "handlers.h"
 | 
				
			||||||
 | 
					#include "sway.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct modifier_key {
 | 
					struct modifier_key {
 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
| 
						 | 
					@ -75,6 +77,18 @@ static bool checkarg(int argc, char *name, enum expected_args type, int val) {
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bindsym_sort(const void *_lbind, const void *_rbind) {
 | 
				
			||||||
 | 
						const struct sway_binding *lbind = *(void **)_lbind;
 | 
				
			||||||
 | 
						const struct sway_binding *rbind = *(void **)_rbind;
 | 
				
			||||||
 | 
						unsigned int lmod = 0, rmod = 0, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Count how any modifiers are pressed
 | 
				
			||||||
 | 
						for (i = 0; i < 8 * sizeof(lbind->modifiers); ++i) {
 | 
				
			||||||
 | 
							lmod += lbind->modifiers & 1 << i;
 | 
				
			||||||
 | 
							rmod += rbind->modifiers & 1 << i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (rbind->keys->length + rmod) - (lbind->keys->length + lmod);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
 | 
					static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
	if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) {
 | 
						if (!checkarg(argc, "bindsym", EXPECTED_MORE_THAN, 1)) {
 | 
				
			||||||
| 
						 | 
					@ -104,6 +118,10 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
		xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE);
 | 
							xkb_keysym_t sym = xkb_keysym_from_name(split->items[i], XKB_KEYSYM_CASE_INSENSITIVE);
 | 
				
			||||||
		if (!sym) {
 | 
							if (!sym) {
 | 
				
			||||||
			sway_log(L_ERROR, "bindsym - unknown key %s", (char *)split->items[i]);
 | 
								sway_log(L_ERROR, "bindsym - unknown key %s", (char *)split->items[i]);
 | 
				
			||||||
 | 
								list_free(binding->keys);
 | 
				
			||||||
 | 
								free(binding->command);
 | 
				
			||||||
 | 
								free(binding);
 | 
				
			||||||
 | 
								list_free(split);
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
 | 
							xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
 | 
				
			||||||
| 
						 | 
					@ -113,7 +131,10 @@ static bool cmd_bindsym(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
	list_free(split);
 | 
						list_free(split);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: Check if there are other commands with this key binding
 | 
						// TODO: Check if there are other commands with this key binding
 | 
				
			||||||
	list_add(config->current_mode->bindings, binding);
 | 
						struct sway_mode *mode = config->current_mode;
 | 
				
			||||||
 | 
						list_add(mode->bindings, binding);
 | 
				
			||||||
 | 
						qsort(mode->bindings->items, mode->bindings->length,
 | 
				
			||||||
 | 
								sizeof(mode->bindings->items[0]), bindsym_sort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command);
 | 
						sway_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
| 
						 | 
					@ -166,7 +187,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Close all views
 | 
						// Close all views
 | 
				
			||||||
	container_map(&root_container, kill_views, NULL);
 | 
						container_map(&root_container, kill_views, NULL);
 | 
				
			||||||
	exit(0);
 | 
						sway_terminate();
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,43 +202,28 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
		if (view->type != C_VIEW) {
 | 
							if (view->type != C_VIEW) {
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		int i;
 | 
					 | 
				
			||||||
		// Change from nonfloating to floating
 | 
							// Change from nonfloating to floating
 | 
				
			||||||
		if (!view->is_floating) {
 | 
							if (!view->is_floating) {
 | 
				
			||||||
			view->is_floating = true;
 | 
								// Remove view from its current location
 | 
				
			||||||
			for (i = 0; i < view->parent->children->length; i++) {
 | 
								destroy_container(remove_child(view));
 | 
				
			||||||
				if (view->parent->children->items[i] == view) {
 | 
								
 | 
				
			||||||
					// Try to use desired geometry to set w/h
 | 
								// and move it into workspace floating
 | 
				
			||||||
					if (view->desired_width != -1) {
 | 
								add_floating(active_workspace,view);
 | 
				
			||||||
						view->width = view->desired_width;
 | 
								view->x = (active_workspace->width - view->width)/2;
 | 
				
			||||||
					}
 | 
								view->y = (active_workspace->height - view->height)/2;
 | 
				
			||||||
					if (view->desired_height != -1) {
 | 
								if (view->desired_width != -1) {
 | 
				
			||||||
						view->height = view->desired_height;
 | 
									view->width = view->desired_width;
 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					// Swap from the list of whatever container the view was in
 | 
					 | 
				
			||||||
					// to the workspace->floating list
 | 
					 | 
				
			||||||
					list_del(view->parent->children, i);
 | 
					 | 
				
			||||||
					list_add(active_workspace->floating, view);
 | 
					 | 
				
			||||||
					destroy_container(view->parent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					// Set the new position of the container and arrange windows
 | 
					 | 
				
			||||||
					view->x = (active_workspace->width - view->width)/2;
 | 
					 | 
				
			||||||
					view->y = (active_workspace->height - view->height)/2;
 | 
					 | 
				
			||||||
					sway_log(L_INFO, "Setting container %p to floating at coordinates X:%d Y:%d, W:%d, H:%d", view, view->x, view->y, view->width, view->height);
 | 
					 | 
				
			||||||
					// Change parent to active_workspace
 | 
					 | 
				
			||||||
					view->parent = active_workspace;
 | 
					 | 
				
			||||||
					arrange_windows(active_workspace, -1, -1);
 | 
					 | 
				
			||||||
					return true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								if (view->desired_height != -1) {
 | 
				
			||||||
 | 
									view->height = view->desired_height;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								arrange_windows(active_workspace, -1, -1);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// Delete the view from the floating list and unset its is_floating flag
 | 
								// Delete the view from the floating list and unset its is_floating flag
 | 
				
			||||||
			// Using length-1 as the index is safe because the view must be the currently
 | 
								// Using length-1 as the index is safe because the view must be the currently
 | 
				
			||||||
			// focused floating output
 | 
								// focused floating output
 | 
				
			||||||
			list_del(active_workspace->floating, active_workspace->floating->length - 1);
 | 
								remove_child(view);
 | 
				
			||||||
			view->is_floating = false;
 | 
								view->is_floating = false;
 | 
				
			||||||
			active_workspace->focused = NULL;
 | 
					 | 
				
			||||||
			// Get the properly focused container, and add in the view there
 | 
								// Get the properly focused container, and add in the view there
 | 
				
			||||||
			swayc_t *focused = container_under_pointer();
 | 
								swayc_t *focused = container_under_pointer();
 | 
				
			||||||
			// If focused is null, it's because the currently focused container is a workspace
 | 
								// If focused is null, it's because the currently focused container is a workspace
 | 
				
			||||||
| 
						 | 
					@ -228,21 +234,20 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sway_log(L_DEBUG, "Non-floating focused container is %p", focused);
 | 
								sway_log(L_DEBUG, "Non-floating focused container is %p", focused);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			//Case of focused workspace, just create as child of it
 | 
								// Case of focused workspace, just create as child of it
 | 
				
			||||||
			if (focused->type == C_WORKSPACE) {
 | 
								if (focused->type == C_WORKSPACE) {
 | 
				
			||||||
				add_child(focused, view);
 | 
									add_child(focused, view);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			//Regular case, create as sibling of current container
 | 
								// Regular case, create as sibling of current container
 | 
				
			||||||
			else {
 | 
								else {
 | 
				
			||||||
				add_sibling(focused, view);
 | 
									add_sibling(focused, view);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Refocus on the view once its been put back into the layout
 | 
								// Refocus on the view once its been put back into the layout
 | 
				
			||||||
			set_focused_container(view);
 | 
								view->width = view->height = 0;
 | 
				
			||||||
			arrange_windows(active_workspace, -1, -1);
 | 
								arrange_windows(active_workspace, -1, -1);
 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							set_focused_container(view);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,11 +255,29 @@ static bool cmd_floating_mod(struct sway_config *config, int argc, char **argv)
 | 
				
			||||||
	if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) {
 | 
						if (!checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1)) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	config->floating_mod = xkb_keysym_from_name(argv[0], XKB_KEYSYM_CASE_INSENSITIVE);
 | 
						int i, j;
 | 
				
			||||||
 | 
						list_t *split = split_string(argv[0], "+");
 | 
				
			||||||
 | 
						config->floating_mod = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// set modifer keys
 | 
				
			||||||
 | 
						for (i = 0; i < split->length; ++i) {
 | 
				
			||||||
 | 
							for (j = 0; j < sizeof(modifiers) / sizeof(struct modifier_key); ++j) {
 | 
				
			||||||
 | 
								if (strcasecmp(modifiers[j].name, split->items[i]) == 0) {
 | 
				
			||||||
 | 
									config->floating_mod |= modifiers[j].mod;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						list_free(split);
 | 
				
			||||||
 | 
						if (!config->floating_mod) {
 | 
				
			||||||
 | 
							sway_log(L_ERROR, "bindsym - unknown keys %s", argv[0]);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
 | 
					static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
 | 
						static int floating_toggled_index = 0;
 | 
				
			||||||
 | 
						static int tiled_toggled_index = 0;
 | 
				
			||||||
	if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) {
 | 
						if (!checkarg(argc, "focus", EXPECTED_EQUAL_TO, 1)) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -268,7 +291,44 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
		return move_focus(MOVE_DOWN);
 | 
							return move_focus(MOVE_DOWN);
 | 
				
			||||||
	} else if (strcasecmp(argv[0], "parent") == 0) {
 | 
						} else if (strcasecmp(argv[0], "parent") == 0) {
 | 
				
			||||||
		return move_focus(MOVE_PARENT);
 | 
							return move_focus(MOVE_PARENT);
 | 
				
			||||||
 | 
						} else if (strcasecmp(argv[0], "mode_toggle") == 0) {
 | 
				
			||||||
 | 
							int i;
 | 
				
			||||||
 | 
							swayc_t *focused = get_focused_view(active_workspace);
 | 
				
			||||||
 | 
							if (focused->is_floating) {
 | 
				
			||||||
 | 
								if (active_workspace->children->length > 0) {
 | 
				
			||||||
 | 
									for (i = 0;i < active_workspace->floating->length; i++) {
 | 
				
			||||||
 | 
										if (active_workspace->floating->items[i] == focused) {
 | 
				
			||||||
 | 
											floating_toggled_index = i;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (active_workspace->children->length > tiled_toggled_index) {
 | 
				
			||||||
 | 
										set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index]));
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										set_focused_container(get_focused_view(active_workspace->children->items[0]));
 | 
				
			||||||
 | 
										tiled_toggled_index = 0;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (active_workspace->floating->length > 0) {
 | 
				
			||||||
 | 
									for (i = 0;i < active_workspace->children->length; i++) {
 | 
				
			||||||
 | 
										if (active_workspace->children->items[i] == focused) {
 | 
				
			||||||
 | 
											tiled_toggled_index = i;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (active_workspace->floating->length > floating_toggled_index) {
 | 
				
			||||||
 | 
										swayc_t *floating = active_workspace->floating->items[floating_toggled_index];
 | 
				
			||||||
 | 
										set_focused_container(get_focused_view(floating));
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1];
 | 
				
			||||||
 | 
										set_focused_container(get_focused_view(floating));
 | 
				
			||||||
 | 
										tiled_toggled_index = active_workspace->floating->length - 1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -303,6 +363,42 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool cmd_gaps(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
 | 
						if (!checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1)) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (argc == 1) {
 | 
				
			||||||
 | 
							char *end;
 | 
				
			||||||
 | 
							int amount = (int)strtol(argv[0], &end, 10);
 | 
				
			||||||
 | 
							if (errno == ERANGE || amount == 0) {
 | 
				
			||||||
 | 
								errno = 0;
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (config->gaps_inner == 0) {
 | 
				
			||||||
 | 
								config->gaps_inner = amount;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (config->gaps_outer == 0) {
 | 
				
			||||||
 | 
								config->gaps_outer = amount;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (argc == 2) {
 | 
				
			||||||
 | 
							char *end;
 | 
				
			||||||
 | 
							int amount = (int)strtol(argv[1], &end, 10);
 | 
				
			||||||
 | 
							if (errno == ERANGE || amount == 0) {
 | 
				
			||||||
 | 
								errno = 0;
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (strcasecmp(argv[0], "inner") == 0) {
 | 
				
			||||||
 | 
								config->gaps_inner = amount;
 | 
				
			||||||
 | 
							} else if (strcasecmp(argv[0], "outer") == 0) {
 | 
				
			||||||
 | 
								config->gaps_outer = amount;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool cmd_kill(struct sway_config *config, int argc, char **argv) {
 | 
					static bool cmd_kill(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
| 
						 | 
					@ -316,7 +412,6 @@ static bool cmd_layout(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	swayc_t *parent = get_focused_container(&root_container);
 | 
						swayc_t *parent = get_focused_container(&root_container);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (parent->type == C_VIEW) {
 | 
						while (parent->type == C_VIEW) {
 | 
				
			||||||
		parent = parent->parent;
 | 
							parent = parent->parent;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -341,7 +436,7 @@ static bool cmd_reload(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
	if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) {
 | 
						if (!checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0)) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!load_config()) {
 | 
						if (!load_config(NULL)) { // TODO: Use config given from -c
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	arrange_windows(&root_container, -1, -1);
 | 
						arrange_windows(&root_container, -1, -1);
 | 
				
			||||||
| 
						 | 
					@ -435,14 +530,12 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
	swayc_t *container = get_focused_view(&root_container);
 | 
						swayc_t *container = get_focused_view(&root_container);
 | 
				
			||||||
	bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0;
 | 
						bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0;
 | 
				
			||||||
	wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current);
 | 
						wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current);
 | 
				
			||||||
	//Resize workspace if going from  fullscreen -> notfullscreen
 | 
						// Resize workspace if going from  fullscreen -> notfullscreen
 | 
				
			||||||
	//otherwise just resize container
 | 
						// otherwise just resize container
 | 
				
			||||||
	if (current) {
 | 
						if (current) {
 | 
				
			||||||
		while (container->type != C_WORKSPACE) {
 | 
							container = swayc_parent_by_type(container, C_WORKSPACE);
 | 
				
			||||||
			container = container->parent;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	//Only resize container when going into fullscreen
 | 
						// Only resize container when going into fullscreen
 | 
				
			||||||
	arrange_windows(container, -1, -1);
 | 
						arrange_windows(container, -1, -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
| 
						 | 
					@ -508,6 +601,7 @@ static struct cmd_handler handlers[] = {
 | 
				
			||||||
	{ "focus", cmd_focus },
 | 
						{ "focus", cmd_focus },
 | 
				
			||||||
	{ "focus_follows_mouse", cmd_focus_follows_mouse },
 | 
						{ "focus_follows_mouse", cmd_focus_follows_mouse },
 | 
				
			||||||
	{ "fullscreen", cmd_fullscreen },
 | 
						{ "fullscreen", cmd_fullscreen },
 | 
				
			||||||
 | 
						{ "gaps", cmd_gaps },
 | 
				
			||||||
	{ "kill", cmd_kill },
 | 
						{ "kill", cmd_kill },
 | 
				
			||||||
	{ "layout", cmd_layout },
 | 
						{ "layout", cmd_layout },
 | 
				
			||||||
	{ "log_colors", cmd_log_colors },
 | 
						{ "log_colors", cmd_log_colors },
 | 
				
			||||||
| 
						 | 
					@ -606,7 +700,7 @@ bool handle_command(struct sway_config *config, char *exec) {
 | 
				
			||||||
		char **argv = split_directive(exec + strlen(handler->command), &argc);
 | 
							char **argv = split_directive(exec + strlen(handler->command), &argc);
 | 
				
			||||||
		int i;
 | 
							int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		 //Perform var subs on all parts of the command
 | 
							 // Perform var subs on all parts of the command
 | 
				
			||||||
		 for (i = 0; i < argc; ++i) {
 | 
							 for (i = 0; i < argc; ++i) {
 | 
				
			||||||
			 argv[i] = do_var_replacement(config, argv[i]);
 | 
								 argv[i] = do_var_replacement(config, argv[i]);
 | 
				
			||||||
		 }
 | 
							 }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										228
									
								
								sway/config.c
									
										
									
									
									
								
							
							
						
						
									
										228
									
								
								sway/config.c
									
										
									
									
									
								
							| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "commands.h"
 | 
					#include "commands.h"
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sway_config *config;
 | 
					struct sway_config *config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,121 +16,143 @@ static bool exists(const char *path) {
 | 
				
			||||||
	return access(path, R_OK) != -1;
 | 
						return access(path, R_OK) != -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void config_defaults(struct sway_config *config) {
 | 
				
			||||||
 | 
						config->symbols = create_list();
 | 
				
			||||||
 | 
						config->modes = create_list();
 | 
				
			||||||
 | 
						config->cmd_queue = create_list();
 | 
				
			||||||
 | 
						config->workspace_outputs = create_list();
 | 
				
			||||||
 | 
						config->current_mode = malloc(sizeof(struct sway_mode));
 | 
				
			||||||
 | 
						config->current_mode->name = NULL;
 | 
				
			||||||
 | 
						config->current_mode->bindings = create_list();
 | 
				
			||||||
 | 
						list_add(config->modes, config->current_mode);
 | 
				
			||||||
 | 
						// Flags
 | 
				
			||||||
 | 
						config->focus_follows_mouse = true;
 | 
				
			||||||
 | 
						config->mouse_warping = true;
 | 
				
			||||||
 | 
						config->reloading = false;
 | 
				
			||||||
 | 
						config->active = false;
 | 
				
			||||||
 | 
						config->failed = false;
 | 
				
			||||||
 | 
						config->gaps_inner = 0;
 | 
				
			||||||
 | 
						config->gaps_outer = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_mode(struct sway_mode *mode) {
 | 
				
			||||||
 | 
						free(mode->name);
 | 
				
			||||||
 | 
						free_flat_list(mode->bindings);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void free_config(struct sway_config *config) {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < config->modes->length; ++i) {
 | 
				
			||||||
 | 
							free_mode((struct sway_mode *)config->modes->items[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free_flat_list(config->modes);
 | 
				
			||||||
 | 
						for (i = 0; i < config->workspace_outputs->length; ++i) {
 | 
				
			||||||
 | 
							struct workspace_output *wso = config->workspace_outputs->items[i];
 | 
				
			||||||
 | 
							free(wso->output);
 | 
				
			||||||
 | 
							free(wso->workspace);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free_flat_list(config->workspace_outputs);
 | 
				
			||||||
 | 
						free_flat_list(config->cmd_queue);
 | 
				
			||||||
 | 
						for (i = 0; i < config->symbols->length; ++i) {
 | 
				
			||||||
 | 
							struct sway_variable *sym = config->symbols->items[i];
 | 
				
			||||||
 | 
							free(sym->name);
 | 
				
			||||||
 | 
							free(sym->value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free_flat_list(config->symbols);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *search_paths[] = {
 | 
				
			||||||
 | 
						"$home/.sway/config",
 | 
				
			||||||
 | 
						"$config/sway/config",
 | 
				
			||||||
 | 
						"/etc/sway/config",
 | 
				
			||||||
 | 
						"$home/.i3/config",
 | 
				
			||||||
 | 
						"$config/.i3/config",
 | 
				
			||||||
 | 
						"/etc/i3/config"
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *get_config_path() {
 | 
					static char *get_config_path() {
 | 
				
			||||||
	char *name = "/.sway/config";
 | 
						char *home = getenv("HOME");
 | 
				
			||||||
	const char *home = getenv("HOME");
 | 
						if (home) {
 | 
				
			||||||
 | 
							home = strdup(getenv("HOME"));
 | 
				
			||||||
	// Check home dir
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in ~/.sway/config");
 | 
					 | 
				
			||||||
	char *temp = malloc(strlen(home) + strlen(name) + 1);
 | 
					 | 
				
			||||||
	strcpy(temp, home);
 | 
					 | 
				
			||||||
	strcat(temp, name);
 | 
					 | 
				
			||||||
	if (exists(temp)) {
 | 
					 | 
				
			||||||
		return temp;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						char *config = getenv("XDG_CONFIG_HOME");
 | 
				
			||||||
	// Check XDG_CONFIG_HOME with fallback to ~/.config/
 | 
						if (config) {
 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_HOME/sway/config");
 | 
							config = strdup(getenv("XDG_CONFIG_HOME"));
 | 
				
			||||||
	char *xdg_config_home = getenv("XDG_CONFIG_HOME");
 | 
						} else if (home) {
 | 
				
			||||||
	if (xdg_config_home == NULL) {
 | 
							const char *def = "/.config";
 | 
				
			||||||
		sway_log(L_DEBUG, "Falling back to ~/.config/sway/config");
 | 
							config = malloc(strlen(home) + strlen(def) + 1);
 | 
				
			||||||
		name = "/.config/sway/config";
 | 
							strcpy(config, home);
 | 
				
			||||||
		temp = malloc(strlen(home) + strlen(name) + 1);
 | 
							strcat(config, def);
 | 
				
			||||||
		strcpy(temp, home);
 | 
					 | 
				
			||||||
		strcat(temp, name);
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		name = "/sway/config";
 | 
							home = strdup("");
 | 
				
			||||||
		temp = malloc(strlen(xdg_config_home) + strlen(name) + 1);
 | 
							config = strdup("");
 | 
				
			||||||
		strcpy(xdg_config_home, home);
 | 
					 | 
				
			||||||
		strcat(temp, name);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (exists(temp)) {
 | 
					 | 
				
			||||||
		return temp;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check /etc/
 | 
						// Set up a temporary config for holding set variables
 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in /etc/sway/config");
 | 
						struct sway_config *temp_config = malloc(sizeof(struct sway_config));
 | 
				
			||||||
	strcpy(temp, "/etc/sway/config");
 | 
						config_defaults(temp_config);
 | 
				
			||||||
	if (exists(temp)) {
 | 
						const char *set_home = "set $home ";
 | 
				
			||||||
		return temp;
 | 
						char *_home = malloc(strlen(home) + strlen(set_home) + 1);
 | 
				
			||||||
 | 
						strcpy(_home, set_home);
 | 
				
			||||||
 | 
						strcat(_home, home);
 | 
				
			||||||
 | 
						handle_command(temp_config, _home);
 | 
				
			||||||
 | 
						free(_home);
 | 
				
			||||||
 | 
						const char *set_config = "set $config ";
 | 
				
			||||||
 | 
						char *_config = malloc(strlen(config) + strlen(set_config) + 1);
 | 
				
			||||||
 | 
						strcpy(_config, set_config);
 | 
				
			||||||
 | 
						strcat(_config, config);
 | 
				
			||||||
 | 
						handle_command(temp_config, _config);
 | 
				
			||||||
 | 
						free(_config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *test = NULL;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < sizeof(search_paths) / sizeof(char *); ++i) {
 | 
				
			||||||
 | 
							test = strdup(search_paths[i]);
 | 
				
			||||||
 | 
							test = do_var_replacement(temp_config, test);
 | 
				
			||||||
 | 
							sway_log(L_DEBUG, "Checking for config at %s", test);
 | 
				
			||||||
 | 
							if (exists(test)) {
 | 
				
			||||||
 | 
								goto _continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							free(test);
 | 
				
			||||||
 | 
							test = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check XDG_CONFIG_DIRS
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS");
 | 
						sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS");
 | 
				
			||||||
	char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS");
 | 
						char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS");
 | 
				
			||||||
	if (xdg_config_dirs != NULL) {
 | 
						if (xdg_config_dirs != NULL) {
 | 
				
			||||||
		list_t *paths = split_string(xdg_config_dirs, ":");
 | 
							list_t *paths = split_string(xdg_config_dirs, ":");
 | 
				
			||||||
		name = "/sway/config";
 | 
							char *name = "/sway/config";
 | 
				
			||||||
		int i;
 | 
							int i;
 | 
				
			||||||
		for (i = 0; i < paths->length; i++ ) {
 | 
							for (i = 0; i < paths->length; i++ ) {
 | 
				
			||||||
			temp = malloc(strlen(paths->items[i]) + strlen(name) + 1);
 | 
								test = malloc(strlen(paths->items[i]) + strlen(name) + 1);
 | 
				
			||||||
			strcpy(temp, paths->items[i]);
 | 
								strcpy(test, paths->items[i]);
 | 
				
			||||||
			strcat(temp, name);
 | 
								strcat(test, name);
 | 
				
			||||||
			if (exists(temp)) {
 | 
								if (exists(test)) {
 | 
				
			||||||
				free_flat_list(paths);
 | 
									free_flat_list(paths);
 | 
				
			||||||
				return temp;
 | 
									return test;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								free(test);
 | 
				
			||||||
 | 
								test = NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		free_flat_list(paths);
 | 
							free_flat_list(paths);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//Now fall back to i3 paths and try the same thing
 | 
					_continue:
 | 
				
			||||||
	name = "/.i3/config";
 | 
						free_config(temp_config);
 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in ~/.i3/config");
 | 
						free(home);
 | 
				
			||||||
	temp = malloc(strlen(home) + strlen(name) + 1);
 | 
						free(config);
 | 
				
			||||||
	strcpy(temp, home);
 | 
						return test;
 | 
				
			||||||
	strcat(temp, name);
 | 
					 | 
				
			||||||
	if (exists(temp)) {
 | 
					 | 
				
			||||||
		return temp;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_HOME/i3/config");
 | 
					 | 
				
			||||||
	if (xdg_config_home == NULL) {
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG, "Falling back to ~/.config/i3/config");
 | 
					 | 
				
			||||||
		name = "/.config/i3/config";
 | 
					 | 
				
			||||||
		temp = malloc(strlen(home) + strlen(name) + 1);
 | 
					 | 
				
			||||||
		strcpy(temp, home);
 | 
					 | 
				
			||||||
		strcat(temp, name);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		name = "/i3/config";
 | 
					 | 
				
			||||||
		temp = malloc(strlen(xdg_config_home) + strlen(name) + 1);
 | 
					 | 
				
			||||||
		strcpy(xdg_config_home, home);
 | 
					 | 
				
			||||||
		strcat(temp, name);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (exists(temp)) {
 | 
					 | 
				
			||||||
		return temp;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in /etc/i3/config");
 | 
					 | 
				
			||||||
	strcpy(temp, "/etc/i3/config");
 | 
					 | 
				
			||||||
	if (exists(temp)) {
 | 
					 | 
				
			||||||
		return temp;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS");
 | 
					 | 
				
			||||||
	if (xdg_config_dirs != NULL) {
 | 
					 | 
				
			||||||
		list_t *paths = split_string(xdg_config_dirs, ":");
 | 
					 | 
				
			||||||
		name = "/i3/config";
 | 
					 | 
				
			||||||
		int i;
 | 
					 | 
				
			||||||
		for (i = 0; i < paths->length; i++ ) {
 | 
					 | 
				
			||||||
			temp = malloc(strlen(paths->items[i]) + strlen(name) + 1);
 | 
					 | 
				
			||||||
			strcpy(temp, paths->items[i]);
 | 
					 | 
				
			||||||
			strcat(temp, name);
 | 
					 | 
				
			||||||
			if (exists(temp)) {
 | 
					 | 
				
			||||||
				free_flat_list(paths);
 | 
					 | 
				
			||||||
				return temp;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		free_flat_list(paths);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool load_config(void) {
 | 
					bool load_config(const char *file) {
 | 
				
			||||||
	sway_log(L_INFO, "Loading config");
 | 
						sway_log(L_INFO, "Loading config");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *path = get_config_path();
 | 
						char *path;
 | 
				
			||||||
 | 
						if (file != NULL) {
 | 
				
			||||||
 | 
							path = strdup(file);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							path = get_config_path();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (path == NULL) {
 | 
						if (path == NULL) {
 | 
				
			||||||
		sway_log(L_ERROR, "Unable to find a config file!");
 | 
							sway_log(L_ERROR, "Unable to find a config file!");
 | 
				
			||||||
| 
						 | 
					@ -155,23 +178,6 @@ bool load_config(void) {
 | 
				
			||||||
	return config_load_success;
 | 
						return config_load_success;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void config_defaults(struct sway_config *config) {
 | 
					 | 
				
			||||||
	config->symbols = create_list();
 | 
					 | 
				
			||||||
	config->modes = create_list();
 | 
					 | 
				
			||||||
	config->cmd_queue = create_list();
 | 
					 | 
				
			||||||
	config->workspace_outputs = create_list();
 | 
					 | 
				
			||||||
	config->current_mode = malloc(sizeof(struct sway_mode));
 | 
					 | 
				
			||||||
	config->current_mode->name = NULL;
 | 
					 | 
				
			||||||
	config->current_mode->bindings = create_list();
 | 
					 | 
				
			||||||
	list_add(config->modes, config->current_mode);
 | 
					 | 
				
			||||||
	// Flags
 | 
					 | 
				
			||||||
	config->focus_follows_mouse = true;
 | 
					 | 
				
			||||||
	config->mouse_warping = true;
 | 
					 | 
				
			||||||
	config->reloading = false;
 | 
					 | 
				
			||||||
	config->active = false;
 | 
					 | 
				
			||||||
	config->failed = false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool read_config(FILE *file, bool is_active) {
 | 
					bool read_config(FILE *file, bool is_active) {
 | 
				
			||||||
	struct sway_config *temp_config = malloc(sizeof(struct sway_config));
 | 
						struct sway_config *temp_config = malloc(sizeof(struct sway_config));
 | 
				
			||||||
	config_defaults(temp_config);
 | 
						config_defaults(temp_config);
 | 
				
			||||||
| 
						 | 
					@ -188,8 +194,8 @@ bool read_config(FILE *file, bool is_active) {
 | 
				
			||||||
	while (!feof(file)) {
 | 
						while (!feof(file)) {
 | 
				
			||||||
		int _;
 | 
							int _;
 | 
				
			||||||
		char *line = read_line(file);
 | 
							char *line = read_line(file);
 | 
				
			||||||
		line = strip_comments(line);
 | 
					 | 
				
			||||||
		line = strip_whitespace(line, &_);
 | 
							line = strip_whitespace(line, &_);
 | 
				
			||||||
 | 
							line = strip_comments(line);
 | 
				
			||||||
		if (!line[0]) {
 | 
							if (!line[0]) {
 | 
				
			||||||
			goto _continue;
 | 
								goto _continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -225,6 +231,8 @@ _continue:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (is_active) {
 | 
						if (is_active) {
 | 
				
			||||||
		temp_config->reloading = false;
 | 
							temp_config->reloading = false;
 | 
				
			||||||
 | 
							container_map(&root_container, reset_gaps, NULL);
 | 
				
			||||||
 | 
							arrange_windows(&root_container, -1, -1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	config = temp_config;
 | 
						config = temp_config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										166
									
								
								sway/container.c
									
										
									
									
									
								
							
							
						
						
									
										166
									
								
								sway/container.c
									
										
									
									
									
								
							| 
						 | 
					@ -8,53 +8,57 @@
 | 
				
			||||||
#include "layout.h"
 | 
					#include "layout.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ASSERT_NONNULL(PTR) \
 | 
				
			||||||
 | 
						sway_assert (PTR, "%s: " #PTR "must be non-null", __func__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static swayc_t *new_swayc(enum swayc_types type) {
 | 
					static swayc_t *new_swayc(enum swayc_types type) {
 | 
				
			||||||
	swayc_t *c = calloc(1, sizeof(swayc_t));
 | 
						swayc_t *c = calloc(1, sizeof(swayc_t));
 | 
				
			||||||
	c->handle = -1;
 | 
						c->handle = -1;
 | 
				
			||||||
	c->layout = L_NONE;
 | 
						c->layout = L_NONE;
 | 
				
			||||||
	c->type = type;
 | 
						c->type = type;
 | 
				
			||||||
	c->weight  = 1;
 | 
					 | 
				
			||||||
	if (type != C_VIEW) {
 | 
						if (type != C_VIEW) {
 | 
				
			||||||
		c->children = create_list();
 | 
							c->children = create_list();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return c;
 | 
						return c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void free_swayc(swayc_t *c) {
 | 
					static void free_swayc(swayc_t *cont) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(cont)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// TODO does not properly handle containers with children,
 | 
						// TODO does not properly handle containers with children,
 | 
				
			||||||
	// TODO but functions that call this usually check for that
 | 
						// TODO but functions that call this usually check for that
 | 
				
			||||||
	if (c->children) {
 | 
						if (cont->children) {
 | 
				
			||||||
		if (c->children->length) {
 | 
							if (cont->children->length) {
 | 
				
			||||||
			int i;
 | 
								int i;
 | 
				
			||||||
			for (i = 0; i < c->children->length; ++i) {
 | 
								for (i = 0; i < cont->children->length; ++i) {
 | 
				
			||||||
				free_swayc(c->children->items[i]);
 | 
									free_swayc(cont->children->items[i]);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		list_free(c->children);
 | 
							list_free(cont->children);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (c->floating) {
 | 
						if (cont->floating) {
 | 
				
			||||||
		if (c->floating->length) {
 | 
							if (cont->floating->length) {
 | 
				
			||||||
			int i;
 | 
								int i;
 | 
				
			||||||
			for (i = 0; i < c->floating->length; ++i) {
 | 
								for (i = 0; i < cont->floating->length; ++i) {
 | 
				
			||||||
				free_swayc(c->floating->items[i]);
 | 
									free_swayc(cont->floating->items[i]);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		list_free(c->floating);
 | 
							list_free(cont->floating);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (c->parent) {
 | 
						if (cont->parent) {
 | 
				
			||||||
		remove_child(c);
 | 
							remove_child(cont);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (c->name) {
 | 
						if (cont->name) {
 | 
				
			||||||
		free(c->name);
 | 
							free(cont->name);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	free(c);
 | 
						free(cont);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* New containers */
 | 
					// New containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool workspace_test(swayc_t *view, void *name) {
 | 
					static bool workspace_test(swayc_t *view, void *name) {
 | 
				
			||||||
	return strcasecmp(view->name, (char *)name);
 | 
						return strcasecmp(view->name, (char *)name) == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *new_output(wlc_handle handle) {
 | 
					swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
| 
						 | 
					@ -67,6 +71,7 @@ swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
	output->height = size->h;
 | 
						output->height = size->h;
 | 
				
			||||||
	output->handle = handle;
 | 
						output->handle = handle;
 | 
				
			||||||
	output->name = name ? strdup(name) : NULL;
 | 
						output->name = name ? strdup(name) : NULL;
 | 
				
			||||||
 | 
						output->gaps = config->gaps_outer + config->gaps_inner / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	add_child(&root_container, output);
 | 
						add_child(&root_container, output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,8 +85,10 @@ swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
				sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output);
 | 
									sway_log(L_DEBUG, "Matched workspace to output: %s for %s", wso->workspace, wso->output);
 | 
				
			||||||
				// Check if any other workspaces are using this name
 | 
									// Check if any other workspaces are using this name
 | 
				
			||||||
				if (find_container(&root_container, workspace_test, wso->workspace)) {
 | 
									if (find_container(&root_container, workspace_test, wso->workspace)) {
 | 
				
			||||||
 | 
										sway_log(L_DEBUG, "But it's already taken");
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									sway_log(L_DEBUG, "So we're going to use it");
 | 
				
			||||||
				ws_name = strdup(wso->workspace);
 | 
									ws_name = strdup(wso->workspace);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -101,10 +108,15 @@ swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *new_workspace(swayc_t *output, const char *name) {
 | 
					swayc_t *new_workspace(swayc_t *output, const char *name) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(output)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle);
 | 
						sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle);
 | 
				
			||||||
	swayc_t *workspace = new_swayc(C_WORKSPACE);
 | 
						swayc_t *workspace = new_swayc(C_WORKSPACE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	workspace->layout = L_HORIZ; // TODO: default layout
 | 
						workspace->layout = L_HORIZ; // TODO: default layout
 | 
				
			||||||
 | 
						workspace->x = output->x;
 | 
				
			||||||
 | 
						workspace->y = output->y;
 | 
				
			||||||
	workspace->width = output->width;
 | 
						workspace->width = output->width;
 | 
				
			||||||
	workspace->height = output->height;
 | 
						workspace->height = output->height;
 | 
				
			||||||
	workspace->name = strdup(name);
 | 
						workspace->name = strdup(name);
 | 
				
			||||||
| 
						 | 
					@ -116,6 +128,9 @@ swayc_t *new_workspace(swayc_t *output, const char *name) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
 | 
					swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(child)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	swayc_t *cont = new_swayc(C_CONTAINER);
 | 
						swayc_t *cont = new_swayc(C_CONTAINER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sway_log(L_DEBUG, "creating container %p around %p", cont, child);
 | 
						sway_log(L_DEBUG, "creating container %p around %p", cont, child);
 | 
				
			||||||
| 
						 | 
					@ -147,6 +162,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
 | 
				
			||||||
		// give them proper layouts
 | 
							// give them proper layouts
 | 
				
			||||||
		cont->layout = workspace->layout;
 | 
							cont->layout = workspace->layout;
 | 
				
			||||||
		workspace->layout = layout;
 | 
							workspace->layout = layout;
 | 
				
			||||||
 | 
							set_focused_container_for(workspace, get_focused_view(workspace));
 | 
				
			||||||
	} else { // Or is built around container
 | 
						} else { // Or is built around container
 | 
				
			||||||
		swayc_t *parent = replace_child(child, cont);
 | 
							swayc_t *parent = replace_child(child, cont);
 | 
				
			||||||
		if (parent) {
 | 
							if (parent) {
 | 
				
			||||||
| 
						 | 
					@ -157,6 +173,9 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
 | 
					swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(sibling)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	const char *title = wlc_view_get_title(handle);
 | 
						const char *title = wlc_view_get_title(handle);
 | 
				
			||||||
	swayc_t *view = new_swayc(C_VIEW);
 | 
						swayc_t *view = new_swayc(C_VIEW);
 | 
				
			||||||
	sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d",
 | 
						sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d",
 | 
				
			||||||
| 
						 | 
					@ -166,11 +185,15 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
 | 
				
			||||||
	view->name = title ? strdup(title) : NULL;
 | 
						view->name = title ? strdup(title) : NULL;
 | 
				
			||||||
	view->visible = true;
 | 
						view->visible = true;
 | 
				
			||||||
	view->is_focused = true;
 | 
						view->is_focused = true;
 | 
				
			||||||
 | 
						// Setup geometry
 | 
				
			||||||
 | 
						const struct wlc_geometry* geometry = wlc_view_get_geometry(handle);
 | 
				
			||||||
 | 
						view->width = 0;
 | 
				
			||||||
 | 
						view->height = 0;
 | 
				
			||||||
 | 
						view->desired_width = geometry->size.w;
 | 
				
			||||||
 | 
						view->desired_height = geometry->size.h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view->desired_width = -1;
 | 
						view->gaps = config->gaps_inner;
 | 
				
			||||||
	view->desired_height = -1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: properly set this
 | 
					 | 
				
			||||||
	view->is_floating = false;
 | 
						view->is_floating = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sibling->type == C_WORKSPACE) {
 | 
						if (sibling->type == C_WORKSPACE) {
 | 
				
			||||||
| 
						 | 
					@ -196,8 +219,9 @@ swayc_t *new_floating_view(wlc_handle handle) {
 | 
				
			||||||
	// Set the geometry of the floating view
 | 
						// Set the geometry of the floating view
 | 
				
			||||||
	const struct wlc_geometry* geometry = wlc_view_get_geometry(handle);
 | 
						const struct wlc_geometry* geometry = wlc_view_get_geometry(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view->x = geometry->origin.x;
 | 
						// give it requested geometry, but place in center
 | 
				
			||||||
	view->y = geometry->origin.y;
 | 
						view->x = (active_workspace->width - geometry->size.w) / 2;
 | 
				
			||||||
 | 
						view->y = (active_workspace->height- geometry->size.h) / 2;
 | 
				
			||||||
	view->width = geometry->size.w;
 | 
						view->width = geometry->size.w;
 | 
				
			||||||
	view->height = geometry->size.h;
 | 
						view->height = geometry->size.h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,9 +239,12 @@ swayc_t *new_floating_view(wlc_handle handle) {
 | 
				
			||||||
	return view;
 | 
						return view;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Destroy container */
 | 
					// Destroy container
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *destroy_output(swayc_t *output) {
 | 
					swayc_t *destroy_output(swayc_t *output) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(output)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (output->children->length == 0) {
 | 
						if (output->children->length == 0) {
 | 
				
			||||||
		// TODO move workspaces to other outputs
 | 
							// TODO move workspaces to other outputs
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -227,23 +254,21 @@ swayc_t *destroy_output(swayc_t *output) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *destroy_workspace(swayc_t *workspace) {
 | 
					swayc_t *destroy_workspace(swayc_t *workspace) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(workspace)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	// NOTE: This is called from elsewhere without checking children length
 | 
						// NOTE: This is called from elsewhere without checking children length
 | 
				
			||||||
	// TODO move containers to other workspaces?
 | 
						// TODO move containers to other workspaces?
 | 
				
			||||||
	// for now just dont delete
 | 
						// for now just dont delete
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Do not destroy this if it's the last workspace on this output
 | 
						// Do not destroy this if it's the last workspace on this output
 | 
				
			||||||
	swayc_t *output = workspace->parent;
 | 
						swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT);
 | 
				
			||||||
	while (output && output->type != C_OUTPUT) {
 | 
						if (output && output->children->length == 1) {
 | 
				
			||||||
		output = output->parent;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (output) {
 | 
					 | 
				
			||||||
		if (output->children->length == 1) {
 | 
					 | 
				
			||||||
			return NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (workspace->children->length == 0) {
 | 
						if (workspace->children->length == 0) {
 | 
				
			||||||
		sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name);
 | 
							sway_log(L_DEBUG, "%s: '%s'", __func__, workspace->name);
 | 
				
			||||||
		swayc_t *parent = workspace->parent;
 | 
							swayc_t *parent = workspace->parent;
 | 
				
			||||||
		free_swayc(workspace);
 | 
							free_swayc(workspace);
 | 
				
			||||||
		return parent;
 | 
							return parent;
 | 
				
			||||||
| 
						 | 
					@ -252,19 +277,20 @@ swayc_t *destroy_workspace(swayc_t *workspace) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *destroy_container(swayc_t *container) {
 | 
					swayc_t *destroy_container(swayc_t *container) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(container)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	while (container->children->length == 0 && container->type == C_CONTAINER) {
 | 
						while (container->children->length == 0 && container->type == C_CONTAINER) {
 | 
				
			||||||
		sway_log(L_DEBUG, "Container: Destroying container '%p'", container);
 | 
							sway_log(L_DEBUG, "Container: Destroying container '%p'", container);
 | 
				
			||||||
		swayc_t *parent = container->parent;
 | 
							swayc_t *parent = container->parent;
 | 
				
			||||||
		free_swayc(container);
 | 
							free_swayc(container);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		container = parent;
 | 
							container = parent;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return container;
 | 
						return container;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *destroy_view(swayc_t *view) {
 | 
					swayc_t *destroy_view(swayc_t *view) {
 | 
				
			||||||
	if (view == NULL) {
 | 
						if (!ASSERT_NONNULL(view)) {
 | 
				
			||||||
		sway_log(L_DEBUG, "Warning: NULL passed into destroy_view");
 | 
					 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sway_log(L_DEBUG, "Destroying view '%p'", view);
 | 
						sway_log(L_DEBUG, "Destroying view '%p'", view);
 | 
				
			||||||
| 
						 | 
					@ -278,6 +304,34 @@ swayc_t *destroy_view(swayc_t *view) {
 | 
				
			||||||
	return parent;
 | 
						return parent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Container lookup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(container)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!sway_assert(type < C_TYPES && type >= C_ROOT, "%s: invalid type", __func__)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							container = container->parent;
 | 
				
			||||||
 | 
						} while(container && container->type != type);
 | 
				
			||||||
 | 
						return container;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(container)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!sway_assert(layout < L_LAYOUTS && layout >= L_NONE, "%s: invalid layout", __func__)) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							container = container->parent;
 | 
				
			||||||
 | 
						} while (container && container->layout != layout);
 | 
				
			||||||
 | 
						return container;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
 | 
					swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
 | 
				
			||||||
	if (!container->children) {
 | 
						if (!container->children) {
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -307,25 +361,27 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) {
 | 
					void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) {
 | 
				
			||||||
	if (!container || !container->children || !container->children->length)  {
 | 
						if (container && container->children && container->children->length)  {
 | 
				
			||||||
		return;
 | 
							int i;
 | 
				
			||||||
	}
 | 
							for (i = 0; i < container->children->length; ++i) {
 | 
				
			||||||
	int i;
 | 
								swayc_t *child = container->children->items[i];
 | 
				
			||||||
	for (i = 0; i < container->children->length; ++i) {
 | 
					 | 
				
			||||||
		swayc_t *child = container->children->items[i];
 | 
					 | 
				
			||||||
		f(child, data);
 | 
					 | 
				
			||||||
		container_map(child, f, data);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (container->type == C_WORKSPACE) {
 | 
					 | 
				
			||||||
		for (i = 0; i < container->floating->length; ++i) {
 | 
					 | 
				
			||||||
			swayc_t *child = container->floating->items[i];
 | 
					 | 
				
			||||||
			f(child, data);
 | 
								f(child, data);
 | 
				
			||||||
			container_map(child, f, data);
 | 
								container_map(child, f, data);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (container->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
								for (i = 0; i < container->floating->length; ++i) {
 | 
				
			||||||
 | 
									swayc_t *child = container->floating->items[i];
 | 
				
			||||||
 | 
									f(child, data);
 | 
				
			||||||
 | 
									container_map(child, f, data);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void set_view_visibility(swayc_t *view, void *data) {
 | 
					void set_view_visibility(swayc_t *view, void *data) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(view)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	uint32_t *p = data;
 | 
						uint32_t *p = data;
 | 
				
			||||||
	if (view->type == C_VIEW) {
 | 
						if (view->type == C_VIEW) {
 | 
				
			||||||
		wlc_view_set_mask(view->handle, *p);
 | 
							wlc_view_set_mask(view->handle, *p);
 | 
				
			||||||
| 
						 | 
					@ -337,3 +393,15 @@ void set_view_visibility(swayc_t *view, void *data) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	view->visible = (*p == 2);
 | 
						view->visible = (*p == 2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void reset_gaps(swayc_t *view, void *data) {
 | 
				
			||||||
 | 
						if (!ASSERT_NONNULL(view)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (view->type == C_OUTPUT) {
 | 
				
			||||||
 | 
							view->gaps = config->gaps_outer;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (view->type == C_VIEW) {
 | 
				
			||||||
 | 
							view->gaps = config->gaps_inner;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										87
									
								
								sway/focus.c
									
										
									
									
									
								
							
							
						
						
									
										87
									
								
								sway/focus.c
									
										
									
									
									
								
							| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include "focus.h"
 | 
					#include "focus.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "workspace.h"
 | 
					#include "workspace.h"
 | 
				
			||||||
 | 
					#include "layout.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool locked_container_focus = false;
 | 
					bool locked_container_focus = false;
 | 
				
			||||||
bool locked_view_focus = false;
 | 
					bool locked_view_focus = false;
 | 
				
			||||||
| 
						 | 
					@ -20,6 +21,8 @@ static void update_focus(swayc_t *c) {
 | 
				
			||||||
		// Case where output changes
 | 
							// Case where output changes
 | 
				
			||||||
		case C_OUTPUT:
 | 
							case C_OUTPUT:
 | 
				
			||||||
			wlc_output_focus(c->handle);
 | 
								wlc_output_focus(c->handle);
 | 
				
			||||||
 | 
								// Set new workspace to the outputs focused workspace
 | 
				
			||||||
 | 
								active_workspace = c->focused;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Case where workspace changes
 | 
							// Case where workspace changes
 | 
				
			||||||
| 
						 | 
					@ -51,74 +54,17 @@ static void update_focus(swayc_t *c) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool move_focus(enum movement_direction direction) {
 | 
					bool move_focus(enum movement_direction direction) {
 | 
				
			||||||
	if (locked_container_focus) {
 | 
						swayc_t *view = get_swayc_in_direction(
 | 
				
			||||||
		return false;
 | 
								get_focused_container(&root_container), direction);
 | 
				
			||||||
	}
 | 
						if (view) {
 | 
				
			||||||
	swayc_t *current = get_focused_container(&root_container);
 | 
							if (direction == MOVE_PARENT) {
 | 
				
			||||||
	if (current->type == C_VIEW
 | 
								set_focused_container(view);
 | 
				
			||||||
		&& wlc_view_get_state(current->handle) & WLC_BIT_FULLSCREEN) {
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	swayc_t *parent = current->parent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (direction == MOVE_PARENT) {
 | 
					 | 
				
			||||||
		if (parent->type == C_OUTPUT) {
 | 
					 | 
				
			||||||
			sway_log(L_DEBUG, "Focus cannot move to parent");
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld",
 | 
								set_focused_container(get_focused_view(view));
 | 
				
			||||||
				current, current->handle, parent, parent->handle);
 | 
					 | 
				
			||||||
			set_focused_container(parent);
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (true) {
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG, "Moving focus away from %p", current);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Test if we can even make a difference here
 | 
					 | 
				
			||||||
		bool can_move = false;
 | 
					 | 
				
			||||||
		int diff = 0;
 | 
					 | 
				
			||||||
		if (direction == MOVE_LEFT || direction == MOVE_RIGHT) {
 | 
					 | 
				
			||||||
			if (parent->layout == L_HORIZ || parent->type == C_ROOT) {
 | 
					 | 
				
			||||||
				can_move = true;
 | 
					 | 
				
			||||||
				diff = direction == MOVE_LEFT ? -1 : 1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if (parent->layout == L_VERT) {
 | 
					 | 
				
			||||||
				can_move = true;
 | 
					 | 
				
			||||||
				diff = direction == MOVE_UP ? -1 : 1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no");
 | 
					 | 
				
			||||||
		if (can_move) {
 | 
					 | 
				
			||||||
			int i;
 | 
					 | 
				
			||||||
			for (i = 0; i < parent->children->length; ++i) {
 | 
					 | 
				
			||||||
				swayc_t *child = parent->children->items[i];
 | 
					 | 
				
			||||||
				if (child == current) {
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			int desired = i + diff;
 | 
					 | 
				
			||||||
			sway_log(L_DEBUG, "Moving from %d to %d", i, desired);
 | 
					 | 
				
			||||||
			if (desired < 0 || desired >= parent->children->length) {
 | 
					 | 
				
			||||||
				can_move = false;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				swayc_t *newview = parent->children->items[desired];
 | 
					 | 
				
			||||||
				set_focused_container(get_focused_view(newview));
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (!can_move) {
 | 
					 | 
				
			||||||
			sway_log(L_DEBUG, "Can't move at current level, moving up tree");
 | 
					 | 
				
			||||||
			current = parent;
 | 
					 | 
				
			||||||
			parent = parent->parent;
 | 
					 | 
				
			||||||
			if (!parent) {
 | 
					 | 
				
			||||||
				// Nothing we can do
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *get_focused_container(swayc_t *parent) {
 | 
					swayc_t *get_focused_container(swayc_t *parent) {
 | 
				
			||||||
| 
						 | 
					@ -142,13 +88,13 @@ void set_focused_container(swayc_t *c) {
 | 
				
			||||||
	// Find previous focused view, and the new focused view, if they are the same return
 | 
						// Find previous focused view, and the new focused view, if they are the same return
 | 
				
			||||||
	swayc_t *focused = get_focused_view(&root_container);
 | 
						swayc_t *focused = get_focused_view(&root_container);
 | 
				
			||||||
	swayc_t *workspace = active_workspace;
 | 
						swayc_t *workspace = active_workspace;
 | 
				
			||||||
	if (focused == get_focused_view(c)) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// update container focus from here to root, making necessary changes along
 | 
						// update container focus from here to root, making necessary changes along
 | 
				
			||||||
	// the way
 | 
						// the way
 | 
				
			||||||
	swayc_t *p = c;
 | 
						swayc_t *p = c;
 | 
				
			||||||
 | 
						if (p->type != C_OUTPUT && p->type != C_ROOT) {
 | 
				
			||||||
 | 
							p->is_focused = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	while (p != &root_container) {
 | 
						while (p != &root_container) {
 | 
				
			||||||
		update_focus(p);
 | 
							update_focus(p);
 | 
				
			||||||
		p = p->parent;
 | 
							p = p->parent;
 | 
				
			||||||
| 
						 | 
					@ -171,8 +117,11 @@ void set_focused_container(swayc_t *c) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// activate current focus
 | 
							// activate current focus
 | 
				
			||||||
		if (p->type == C_VIEW) {
 | 
							if (p->type == C_VIEW) {
 | 
				
			||||||
			wlc_view_focus(p->handle);
 | 
					 | 
				
			||||||
			wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true);
 | 
								wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true);
 | 
				
			||||||
 | 
								// set focus if view_focus is unlocked
 | 
				
			||||||
 | 
								if (!locked_view_focus) {
 | 
				
			||||||
 | 
									wlc_view_focus(p->handle);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										328
									
								
								sway/handlers.c
									
										
									
									
									
								
							
							
						
						
									
										328
									
								
								sway/handlers.c
									
										
									
									
									
								
							| 
						 | 
					@ -13,21 +13,14 @@
 | 
				
			||||||
#include "workspace.h"
 | 
					#include "workspace.h"
 | 
				
			||||||
#include "container.h"
 | 
					#include "container.h"
 | 
				
			||||||
#include "focus.h"
 | 
					#include "focus.h"
 | 
				
			||||||
 | 
					#include "input_state.h"
 | 
				
			||||||
uint32_t keys_pressed[32];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlc_origin mouse_origin;
 | 
					static struct wlc_origin mouse_origin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool m1_held = false;
 | 
					 | 
				
			||||||
static bool m2_held = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool pointer_test(swayc_t *view, void *_origin) {
 | 
					static bool pointer_test(swayc_t *view, void *_origin) {
 | 
				
			||||||
	const struct wlc_origin *origin = _origin;
 | 
						const struct wlc_origin *origin = _origin;
 | 
				
			||||||
	// Determine the output that the view is under
 | 
						// Determine the output that the view is under
 | 
				
			||||||
	swayc_t *parent = view;
 | 
						swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
 | 
				
			||||||
	while (parent->type != C_OUTPUT) {
 | 
					 | 
				
			||||||
		parent = parent->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (origin->x >= view->x && origin->y >= view->y
 | 
						if (origin->x >= view->x && origin->y >= view->y
 | 
				
			||||||
		&& origin->x < view->x + view->width && origin->y < view->y + view->height
 | 
							&& origin->x < view->x + view->width && origin->y < view->y + view->height
 | 
				
			||||||
		&& view->visible && parent == root_container.focused) {
 | 
							&& view->visible && parent == root_container.focused) {
 | 
				
			||||||
| 
						 | 
					@ -86,10 +79,12 @@ swayc_t *container_under_pointer(void) {
 | 
				
			||||||
	return lookup;
 | 
						return lookup;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Handles */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_output_created(wlc_handle output) {
 | 
					static bool handle_output_created(wlc_handle output) {
 | 
				
			||||||
	swayc_t *op = new_output(output);
 | 
						swayc_t *op = new_output(output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//Switch to workspace if we need to
 | 
						// Switch to workspace if we need to
 | 
				
			||||||
	if (active_workspace == NULL) {
 | 
						if (active_workspace == NULL) {
 | 
				
			||||||
		swayc_t *ws = op->children->items[0];
 | 
							swayc_t *ws = op->children->items[0];
 | 
				
			||||||
		workspace_switch(ws);
 | 
							workspace_switch(ws);
 | 
				
			||||||
| 
						 | 
					@ -111,7 +106,7 @@ static void handle_output_destroyed(wlc_handle output) {
 | 
				
			||||||
	if (list->length == 0) {
 | 
						if (list->length == 0) {
 | 
				
			||||||
		active_workspace = NULL;
 | 
							active_workspace = NULL;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		//switch to other outputs active workspace
 | 
							// switch to other outputs active workspace
 | 
				
			||||||
		workspace_switch(((swayc_t *)root_container.children->items[0])->focused);
 | 
							workspace_switch(((swayc_t *)root_container.children->items[0])->focused);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -137,38 +132,64 @@ static void handle_output_focused(wlc_handle output, bool focus) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_view_created(wlc_handle handle) {
 | 
					static bool handle_view_created(wlc_handle handle) {
 | 
				
			||||||
	swayc_t *focused = get_focused_container(&root_container);
 | 
						// if view is child of another view, the use that as focused container
 | 
				
			||||||
 | 
						wlc_handle parent = wlc_view_get_parent(handle);
 | 
				
			||||||
 | 
						swayc_t *focused = NULL;
 | 
				
			||||||
	swayc_t *newview = NULL;
 | 
						swayc_t *newview = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get parent container, to add view in
 | 
				
			||||||
 | 
						if (parent) {
 | 
				
			||||||
 | 
							focused = get_swayc_for_handle(parent, &root_container);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!focused || focused->type == C_OUTPUT) {
 | 
				
			||||||
 | 
							focused = get_focused_container(&root_container);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sway_log(L_DEBUG, "handle:%ld type:%x state:%x parent:%ld "
 | 
				
			||||||
 | 
								"mask:%d (x:%d y:%d w:%d h:%d) title:%s "
 | 
				
			||||||
 | 
								"class:%s appid:%s",
 | 
				
			||||||
 | 
							handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent,
 | 
				
			||||||
 | 
							wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x,
 | 
				
			||||||
 | 
							wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w,
 | 
				
			||||||
 | 
							wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle),
 | 
				
			||||||
 | 
							wlc_view_get_class(handle), wlc_view_get_app_id(handle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO properly figure out how each window should be handled.
 | 
				
			||||||
	switch (wlc_view_get_type(handle)) {
 | 
						switch (wlc_view_get_type(handle)) {
 | 
				
			||||||
	// regular view created regularly
 | 
						// regular view created regularly
 | 
				
			||||||
	case 0:
 | 
						case 0:
 | 
				
			||||||
		newview = new_view(focused, handle);
 | 
							newview = new_view(focused, handle);
 | 
				
			||||||
		wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
 | 
							wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	// takes keyboard focus
 | 
					
 | 
				
			||||||
 | 
						// Dmenu keeps viewfocus, but others with this flag dont, for now simulate
 | 
				
			||||||
 | 
						// dmenu
 | 
				
			||||||
	case WLC_BIT_OVERRIDE_REDIRECT:
 | 
						case WLC_BIT_OVERRIDE_REDIRECT:
 | 
				
			||||||
		sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle);
 | 
					// 		locked_view_focus = true;
 | 
				
			||||||
		locked_view_focus = true;
 | 
					 | 
				
			||||||
		wlc_view_focus(handle);
 | 
							wlc_view_focus(handle);
 | 
				
			||||||
		wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
 | 
							wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
 | 
				
			||||||
		wlc_view_bring_to_front(handle);
 | 
							wlc_view_bring_to_front(handle);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	// Takes container focus
 | 
					
 | 
				
			||||||
 | 
						// Firefox popups have this flag set.
 | 
				
			||||||
	case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
 | 
						case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
 | 
				
			||||||
		sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle);
 | 
					 | 
				
			||||||
		wlc_view_bring_to_front(handle);
 | 
							wlc_view_bring_to_front(handle);
 | 
				
			||||||
		locked_container_focus = true;
 | 
							locked_container_focus = true;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	// set modals as floating containers
 | 
					
 | 
				
			||||||
 | 
						// Modals, get focus, popups do not
 | 
				
			||||||
	case WLC_BIT_MODAL:
 | 
						case WLC_BIT_MODAL:
 | 
				
			||||||
 | 
							wlc_view_focus(handle);
 | 
				
			||||||
		wlc_view_bring_to_front(handle);
 | 
							wlc_view_bring_to_front(handle);
 | 
				
			||||||
		newview = new_floating_view(handle);
 | 
							newview = new_floating_view(handle);
 | 
				
			||||||
	case WLC_BIT_POPUP:
 | 
						case WLC_BIT_POPUP:
 | 
				
			||||||
 | 
							wlc_view_bring_to_front(handle);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (newview) {
 | 
						if (newview) {
 | 
				
			||||||
		set_focused_container(newview);
 | 
							set_focused_container(newview);
 | 
				
			||||||
		arrange_windows(newview->parent, -1, -1);
 | 
							swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT);
 | 
				
			||||||
 | 
							arrange_windows(output, -1, -1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -181,19 +202,19 @@ static void handle_view_destroyed(wlc_handle handle) {
 | 
				
			||||||
	// regular view created regularly
 | 
						// regular view created regularly
 | 
				
			||||||
	case 0:
 | 
						case 0:
 | 
				
			||||||
	case WLC_BIT_MODAL:
 | 
						case WLC_BIT_MODAL:
 | 
				
			||||||
 | 
						case WLC_BIT_POPUP:
 | 
				
			||||||
		if (view) {
 | 
							if (view) {
 | 
				
			||||||
			swayc_t *parent = destroy_view(view);
 | 
								swayc_t *parent = destroy_view(view);
 | 
				
			||||||
			arrange_windows(parent, -1, -1);
 | 
								arrange_windows(parent, -1, -1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	// takes keyboard focus
 | 
						// DMENU has this flag, and takes view_focus, but other things with this
 | 
				
			||||||
 | 
						// flag dont
 | 
				
			||||||
	case WLC_BIT_OVERRIDE_REDIRECT:
 | 
						case WLC_BIT_OVERRIDE_REDIRECT:
 | 
				
			||||||
		locked_view_focus = false;
 | 
					// 		locked_view_focus = false;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	// Takes container focus
 | 
					 | 
				
			||||||
	case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
 | 
						case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
 | 
				
			||||||
		locked_container_focus = false;
 | 
							locked_container_focus = false;
 | 
				
			||||||
	case WLC_BIT_POPUP:
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	set_focused_container(get_focused_view(&root_container));
 | 
						set_focused_container(get_focused_view(&root_container));
 | 
				
			||||||
| 
						 | 
					@ -205,7 +226,7 @@ static void handle_view_focus(wlc_handle view, bool focus) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) {
 | 
					static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry *geometry) {
 | 
				
			||||||
	sway_log(L_DEBUG, "geometry request %d x %d : %d x %d",
 | 
						sway_log(L_DEBUG, "geometry request %d x %d : %d x %d",
 | 
				
			||||||
			geometry->origin.x, geometry->origin.y, geometry->size.w,geometry->size.h);
 | 
								geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h);
 | 
				
			||||||
	// If the view is floating, then apply the geometry.
 | 
						// If the view is floating, then apply the geometry.
 | 
				
			||||||
	// Otherwise save the desired width/height for the view.
 | 
						// Otherwise save the desired width/height for the view.
 | 
				
			||||||
	// This will not do anything for the time being as WLC improperly sends geometry requests
 | 
						// This will not do anything for the time being as WLC improperly sends geometry requests
 | 
				
			||||||
| 
						 | 
					@ -225,21 +246,17 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
 | 
					static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
 | 
				
			||||||
	swayc_t *c = NULL;
 | 
						swayc_t *c = get_swayc_for_handle(view, &root_container);
 | 
				
			||||||
	switch(state) {
 | 
						switch (state) {
 | 
				
			||||||
	case WLC_BIT_FULLSCREEN:
 | 
						case WLC_BIT_FULLSCREEN:
 | 
				
			||||||
		// i3 just lets it become fullscreen
 | 
							// i3 just lets it become fullscreen
 | 
				
			||||||
		wlc_view_set_state(view, state, toggle);
 | 
							wlc_view_set_state(view, state, toggle);
 | 
				
			||||||
		c = get_swayc_for_handle(view, &root_container);
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle);
 | 
					 | 
				
			||||||
		if (c) {
 | 
							if (c) {
 | 
				
			||||||
 | 
								sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle);
 | 
				
			||||||
			arrange_windows(c->parent, -1, -1);
 | 
								arrange_windows(c->parent, -1, -1);
 | 
				
			||||||
			// Set it as focused window for that workspace if its going fullscreen
 | 
								// Set it as focused window for that workspace if its going fullscreen
 | 
				
			||||||
			if (toggle) {
 | 
								if (toggle) {
 | 
				
			||||||
				swayc_t *ws = c;
 | 
									swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE);
 | 
				
			||||||
				while (ws->type != C_WORKSPACE) {
 | 
					 | 
				
			||||||
					ws = ws->parent;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				// Set ws focus to c
 | 
									// Set ws focus to c
 | 
				
			||||||
				set_focused_container_for(ws, c);
 | 
									set_focused_container_for(ws, c);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -248,7 +265,9 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s
 | 
				
			||||||
	case WLC_BIT_MAXIMIZED:
 | 
						case WLC_BIT_MAXIMIZED:
 | 
				
			||||||
	case WLC_BIT_RESIZING:
 | 
						case WLC_BIT_RESIZING:
 | 
				
			||||||
	case WLC_BIT_MOVING:
 | 
						case WLC_BIT_MOVING:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case WLC_BIT_ACTIVATED:
 | 
						case WLC_BIT_ACTIVATED:
 | 
				
			||||||
 | 
							sway_log(L_DEBUG, "View %p requested to be activated", c);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
| 
						 | 
					@ -257,29 +276,38 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
 | 
					static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
 | 
				
			||||||
		uint32_t key, uint32_t sym, enum wlc_key_state state) {
 | 
							uint32_t key, uint32_t sym, enum wlc_key_state state) {
 | 
				
			||||||
	enum { QSIZE = 32 };
 | 
					
 | 
				
			||||||
	if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) {
 | 
						if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	static uint8_t  head = 0;
 | 
					
 | 
				
			||||||
	bool cmd_success = false;
 | 
						// Revert floating container back to original position on keypress
 | 
				
			||||||
 | 
						if (state == WLC_KEY_STATE_PRESSED &&
 | 
				
			||||||
 | 
								(pointer_state.floating.drag || pointer_state.floating.resize)) {
 | 
				
			||||||
 | 
							reset_floating(get_focused_view(&root_container));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_mode *mode = config->current_mode;
 | 
						struct sway_mode *mode = config->current_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sym < 70000 /* bullshit made up number */) {
 | 
				
			||||||
 | 
							if (!isalnum(sym) && sym != ' ' && sym != XKB_KEY_Escape && sym != XKB_KEY_Tab) {
 | 
				
			||||||
 | 
								// God fucking dammit
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Lowercase if necessary
 | 
						// Lowercase if necessary
 | 
				
			||||||
	sym = tolower(sym);
 | 
						sym = tolower(sym);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Find key, if it has been pressed
 | 
					 | 
				
			||||||
	int mid = 0;
 | 
					 | 
				
			||||||
	while (mid < head && keys_pressed[mid] != sym) {
 | 
					 | 
				
			||||||
		++mid;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (state == WLC_KEY_STATE_PRESSED && mid == head && head + 1 < QSIZE) {
 | 
					 | 
				
			||||||
		keys_pressed[head++] = sym;
 | 
					 | 
				
			||||||
	} else if (state == WLC_KEY_STATE_RELEASED && mid < head) {
 | 
					 | 
				
			||||||
		memmove(keys_pressed + mid, keys_pressed + mid + 1, sizeof*keys_pressed * (--head - mid));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// TODO: reminder to check conflicts with mod+q+a versus mod+q
 | 
					 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state == WLC_KEY_STATE_PRESSED) {
 | 
				
			||||||
 | 
							press_key(sym);
 | 
				
			||||||
 | 
						} else { // WLC_KEY_STATE_RELEASED
 | 
				
			||||||
 | 
							release_key(sym);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: reminder to check conflicts with mod+q+a versus mod+q
 | 
				
			||||||
	for (i = 0; i < mode->bindings->length; ++i) {
 | 
						for (i = 0; i < mode->bindings->length; ++i) {
 | 
				
			||||||
		struct sway_binding *binding = mode->bindings->items[i];
 | 
							struct sway_binding *binding = mode->bindings->items[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -287,39 +315,22 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
 | 
				
			||||||
			bool match;
 | 
								bool match;
 | 
				
			||||||
			int j;
 | 
								int j;
 | 
				
			||||||
			for (j = 0; j < binding->keys->length; ++j) {
 | 
								for (j = 0; j < binding->keys->length; ++j) {
 | 
				
			||||||
				match = false;
 | 
					 | 
				
			||||||
				xkb_keysym_t *key = binding->keys->items[j];
 | 
									xkb_keysym_t *key = binding->keys->items[j];
 | 
				
			||||||
				uint8_t k;
 | 
									if ((match = check_key(*key)) == false) {
 | 
				
			||||||
				for (k = 0; k < head; ++k) {
 | 
					 | 
				
			||||||
					if (keys_pressed[k] == *key) {
 | 
					 | 
				
			||||||
						match = true;
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (match == false) {
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (match) {
 | 
								if (match) {
 | 
				
			||||||
				// Remove matched keys from keys_pressed
 | 
					 | 
				
			||||||
				int j;
 | 
					 | 
				
			||||||
				for (j = 0; j < binding->keys->length; ++j) {
 | 
					 | 
				
			||||||
					uint8_t k;
 | 
					 | 
				
			||||||
					for (k = 0; k < head; ++k) {
 | 
					 | 
				
			||||||
						memmove(keys_pressed + k, keys_pressed + k + 1, sizeof*keys_pressed * (--head - k));
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if (state == WLC_KEY_STATE_PRESSED) {
 | 
									if (state == WLC_KEY_STATE_PRESSED) {
 | 
				
			||||||
					cmd_success = handle_command(config, binding->command);
 | 
										handle_command(config, binding->command);
 | 
				
			||||||
 | 
										return true;
 | 
				
			||||||
				} else if (state == WLC_KEY_STATE_RELEASED) {
 | 
									} else if (state == WLC_KEY_STATE_RELEASED) {
 | 
				
			||||||
					// TODO: --released
 | 
										// TODO: --released
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cmd_success;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
 | 
					static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
 | 
				
			||||||
| 
						 | 
					@ -327,119 +338,129 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
 | 
				
			||||||
	static wlc_handle prev_handle = 0;
 | 
						static wlc_handle prev_handle = 0;
 | 
				
			||||||
	mouse_origin = *origin;
 | 
						mouse_origin = *origin;
 | 
				
			||||||
	bool changed_floating = false;
 | 
						bool changed_floating = false;
 | 
				
			||||||
	int i = 0;
 | 
					 | 
				
			||||||
	if (!active_workspace) {
 | 
						if (!active_workspace) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Do checks to determine if proper keys are being held
 | 
						// Do checks to determine if proper keys are being held
 | 
				
			||||||
	swayc_t *view = active_workspace->focused;
 | 
						swayc_t *view = get_focused_view(active_workspace);
 | 
				
			||||||
	if (m1_held && view) {
 | 
						uint32_t edge = 0;
 | 
				
			||||||
 | 
						if (pointer_state.floating.drag && view) {
 | 
				
			||||||
		if (view->is_floating) {
 | 
							if (view->is_floating) {
 | 
				
			||||||
			while (keys_pressed[i++]) {
 | 
								int dx = mouse_origin.x - prev_pos.x;
 | 
				
			||||||
				if (keys_pressed[i] == config->floating_mod) {
 | 
								int dy = mouse_origin.y - prev_pos.y;
 | 
				
			||||||
					int dx = mouse_origin.x - prev_pos.x;
 | 
								view->x += dx;
 | 
				
			||||||
					int dy = mouse_origin.y - prev_pos.y;
 | 
								view->y += dy;
 | 
				
			||||||
					sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y);
 | 
								changed_floating = true;
 | 
				
			||||||
					sway_log(L_DEBUG, "Moving: dx: %d, dy: %d", dx, dy);
 | 
							}
 | 
				
			||||||
 | 
						} else if (pointer_state.floating.resize && view) {
 | 
				
			||||||
 | 
							if (view->is_floating) {
 | 
				
			||||||
 | 
								int dx = mouse_origin.x - prev_pos.x;
 | 
				
			||||||
 | 
								int dy = mouse_origin.y - prev_pos.y;
 | 
				
			||||||
 | 
								int min_sane_w = 100;
 | 
				
			||||||
 | 
								int min_sane_h = 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					view->x += dx;
 | 
								// Move and resize the view based on the dx/dy and mouse position
 | 
				
			||||||
					view->y += dy;
 | 
								int midway_x = view->x + view->width/2;
 | 
				
			||||||
 | 
								int midway_y = view->y + view->height/2;
 | 
				
			||||||
 | 
								if (dx < 0) {
 | 
				
			||||||
 | 
									if (!pointer_state.lock.right) {
 | 
				
			||||||
 | 
										if (view->width > min_sane_w) {
 | 
				
			||||||
 | 
											changed_floating = true;
 | 
				
			||||||
 | 
											view->width += dx;
 | 
				
			||||||
 | 
											edge += WLC_RESIZE_EDGE_RIGHT;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
 | 
				
			||||||
					changed_floating = true;
 | 
										changed_floating = true;
 | 
				
			||||||
					break;
 | 
										view->x += dx;
 | 
				
			||||||
 | 
										view->width -= dx;
 | 
				
			||||||
 | 
										edge += WLC_RESIZE_EDGE_LEFT;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if (dx > 0) {
 | 
				
			||||||
 | 
									if (mouse_origin.x > midway_x && !pointer_state.lock.right) {
 | 
				
			||||||
 | 
										changed_floating = true;
 | 
				
			||||||
 | 
										view->width += dx;
 | 
				
			||||||
 | 
										edge += WLC_RESIZE_EDGE_RIGHT;
 | 
				
			||||||
 | 
									} else if (!pointer_state.lock.left) {
 | 
				
			||||||
 | 
										if (view->width > min_sane_w) {
 | 
				
			||||||
 | 
											changed_floating = true;
 | 
				
			||||||
 | 
											view->x += dx;
 | 
				
			||||||
 | 
											view->width -= dx;
 | 
				
			||||||
 | 
											edge += WLC_RESIZE_EDGE_LEFT;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if (m2_held && view) {
 | 
					 | 
				
			||||||
		if (view->is_floating) {
 | 
					 | 
				
			||||||
			while (keys_pressed[i++]) {
 | 
					 | 
				
			||||||
				if (keys_pressed[i] == config->floating_mod) {
 | 
					 | 
				
			||||||
					int dx = mouse_origin.x - prev_pos.x;
 | 
					 | 
				
			||||||
					int dy = mouse_origin.y - prev_pos.y;
 | 
					 | 
				
			||||||
					sway_log(L_DEBUG, "Moving from px: %d to cx: %d and from py: %d to cy: %d", prev_pos.x, mouse_origin.x, prev_pos.y, mouse_origin.y);
 | 
					 | 
				
			||||||
					sway_log(L_INFO, "Moving: dx: %d, dy: %d", dx, dy);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					// Move and resize the view based on the dx/dy and mouse position
 | 
								if (dy < 0) {
 | 
				
			||||||
					int midway_x = view->x + view->width/2;
 | 
									if (!pointer_state.lock.bottom) {
 | 
				
			||||||
					int midway_y = view->y + view->height/2;
 | 
										if (view->height > min_sane_h) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (dx < 0) {
 | 
					 | 
				
			||||||
						changed_floating = true;
 | 
											changed_floating = true;
 | 
				
			||||||
						if (mouse_origin.x > midway_x) {
 | 
											view->height += dy;
 | 
				
			||||||
							sway_log(L_INFO, "Downsizing view to the left");
 | 
											edge += WLC_RESIZE_EDGE_BOTTOM;
 | 
				
			||||||
							view->width += dx;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							sway_log(L_INFO, "Upsizing view to the left");
 | 
					 | 
				
			||||||
							view->x += dx;
 | 
					 | 
				
			||||||
							view->width -= dx;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else if (dx > 0){
 | 
					 | 
				
			||||||
						changed_floating = true;
 | 
					 | 
				
			||||||
						if (mouse_origin.x > midway_x) {
 | 
					 | 
				
			||||||
							sway_log(L_INFO, "Upsizing to the right");
 | 
					 | 
				
			||||||
							view->width += dx;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							sway_log(L_INFO, "Downsizing to the right");
 | 
					 | 
				
			||||||
							view->x += dx;
 | 
					 | 
				
			||||||
							view->width -= dx;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
									} else if (mouse_origin.y < midway_y && !pointer_state.lock.top) {
 | 
				
			||||||
					if (dy < 0) {
 | 
										changed_floating = true;
 | 
				
			||||||
 | 
										view->y += dy;
 | 
				
			||||||
 | 
										view->height -= dy;
 | 
				
			||||||
 | 
										edge += WLC_RESIZE_EDGE_TOP;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if (dy > 0) {
 | 
				
			||||||
 | 
									if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
 | 
				
			||||||
 | 
										changed_floating = true;
 | 
				
			||||||
 | 
										view->height += dy;
 | 
				
			||||||
 | 
										edge += WLC_RESIZE_EDGE_BOTTOM;
 | 
				
			||||||
 | 
									} else if (!pointer_state.lock.top) {
 | 
				
			||||||
 | 
										if (view->height > min_sane_h) {
 | 
				
			||||||
						changed_floating = true;
 | 
											changed_floating = true;
 | 
				
			||||||
						if (mouse_origin.y > midway_y) {
 | 
											view->y += dy;
 | 
				
			||||||
							sway_log(L_INFO, "Downsizing view to the top");
 | 
											view->height -= dy;
 | 
				
			||||||
							view->height += dy;
 | 
											edge += WLC_RESIZE_EDGE_TOP;
 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							sway_log(L_INFO, "Upsizing the view to the top");
 | 
					 | 
				
			||||||
							view->y += dy;
 | 
					 | 
				
			||||||
							view->height -= dy;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else if (dy > 0) {
 | 
					 | 
				
			||||||
						changed_floating = true;
 | 
					 | 
				
			||||||
						if (mouse_origin.y > midway_y) {
 | 
					 | 
				
			||||||
							sway_log(L_INFO, "Upsizing to the bottom");
 | 
					 | 
				
			||||||
							view->height += dy;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							sway_log(L_INFO, "Downsizing to the bottom");
 | 
					 | 
				
			||||||
							view->y += dy;
 | 
					 | 
				
			||||||
							view->height -= dy;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (config->focus_follows_mouse && prev_handle != handle) {
 | 
						if (config->focus_follows_mouse && prev_handle != handle) {
 | 
				
			||||||
		//Dont change focus if fullscreen
 | 
							// Dont change focus if fullscreen
 | 
				
			||||||
		swayc_t *focused = get_focused_view(view);
 | 
							swayc_t *focused = get_focused_view(view);
 | 
				
			||||||
		if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) {
 | 
							if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)
 | 
				
			||||||
 | 
									&& !(pointer_state.l_held || pointer_state.r_held)) {
 | 
				
			||||||
			set_focused_container(container_under_pointer());
 | 
								set_focused_container(container_under_pointer());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prev_handle = handle;
 | 
						prev_handle = handle;
 | 
				
			||||||
	prev_pos = mouse_origin;
 | 
						prev_pos = mouse_origin;
 | 
				
			||||||
	if (changed_floating) {
 | 
						if (changed_floating) {
 | 
				
			||||||
		arrange_windows(view, -1, -1);
 | 
							struct wlc_geometry geometry = {
 | 
				
			||||||
 | 
								.origin = {
 | 
				
			||||||
 | 
									.x = view->x,
 | 
				
			||||||
 | 
									.y = view->y
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								.size = {
 | 
				
			||||||
 | 
									.w = view->width,
 | 
				
			||||||
 | 
									.h = view->height
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							wlc_view_set_geometry(view->handle, edge, &geometry);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
 | 
					static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers,
 | 
				
			||||||
		uint32_t button, enum wlc_button_state state) {
 | 
							uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) {
 | 
				
			||||||
	swayc_t *focused = get_focused_container(&root_container);
 | 
						swayc_t *focused = get_focused_container(&root_container);
 | 
				
			||||||
	//dont change focus if fullscreen
 | 
						// dont change focus if fullscreen
 | 
				
			||||||
	if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
 | 
						if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (state == WLC_BUTTON_STATE_PRESSED) {
 | 
						if (state == WLC_BUTTON_STATE_PRESSED) {
 | 
				
			||||||
		sway_log(L_DEBUG, "Mouse button %u pressed", button);
 | 
							sway_log(L_DEBUG, "Mouse button %u pressed", button);
 | 
				
			||||||
		if (button == 272) {
 | 
							if (button == M_LEFT_CLICK) {
 | 
				
			||||||
			m1_held = true;
 | 
								pointer_state.l_held = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (button == 273) {
 | 
							if (button == M_RIGHT_CLICK) {
 | 
				
			||||||
			m2_held = true;
 | 
								pointer_state.r_held = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		swayc_t *pointer = container_under_pointer();
 | 
							swayc_t *pointer = container_under_pointer();
 | 
				
			||||||
		set_focused_container(pointer);
 | 
							set_focused_container(pointer);
 | 
				
			||||||
| 
						 | 
					@ -453,15 +474,32 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			arrange_windows(pointer->parent, -1, -1);
 | 
								arrange_windows(pointer->parent, -1, -1);
 | 
				
			||||||
 | 
								if (modifiers->mods & config->floating_mod) {
 | 
				
			||||||
 | 
									int midway_x = pointer->x + pointer->width/2;
 | 
				
			||||||
 | 
									int midway_y = pointer->y + pointer->height/2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									pointer_state.floating.drag = pointer_state.l_held;
 | 
				
			||||||
 | 
									pointer_state.floating.resize = pointer_state.r_held;
 | 
				
			||||||
 | 
									pointer_state.lock.bottom = origin->y < midway_y;
 | 
				
			||||||
 | 
									pointer_state.lock.top = !pointer_state.lock.bottom;
 | 
				
			||||||
 | 
									pointer_state.lock.right = origin->x < midway_x;
 | 
				
			||||||
 | 
									pointer_state.lock.left = !pointer_state.lock.right;
 | 
				
			||||||
 | 
									start_floating(pointer);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// Dont want pointer sent to window while dragging or resizing
 | 
				
			||||||
 | 
								return (pointer_state.floating.drag || pointer_state.floating.resize);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return (pointer && pointer != focused);
 | 
							return (pointer && pointer != focused);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		sway_log(L_DEBUG, "Mouse button %u released", button);
 | 
							sway_log(L_DEBUG, "Mouse button %u released", button);
 | 
				
			||||||
		if (button == 272) {
 | 
							if (button == M_LEFT_CLICK) {
 | 
				
			||||||
			m1_held = false;
 | 
								pointer_state.l_held = false;
 | 
				
			||||||
 | 
								pointer_state.floating.drag = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (button == 273) {
 | 
							if (button == M_RIGHT_CLICK) {
 | 
				
			||||||
			m2_held = false;
 | 
								pointer_state.r_held = false;
 | 
				
			||||||
 | 
								pointer_state.floating.resize = false;
 | 
				
			||||||
 | 
								pointer_state.lock = (struct pointer_lock){false ,false ,false ,false};
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										68
									
								
								sway/input_state.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								sway/input_state.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "input_state.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KEY_STATE_MAX_LENGTH 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static keycode key_state_array[KEY_STATE_MAX_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t find_key(keycode key) {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < KEY_STATE_MAX_LENGTH; ++i) {
 | 
				
			||||||
 | 
							if (key_state_array[i] == key) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool check_key(keycode key) {
 | 
				
			||||||
 | 
						return find_key(key) < KEY_STATE_MAX_LENGTH;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void press_key(keycode key) {
 | 
				
			||||||
 | 
						// Check if key exists
 | 
				
			||||||
 | 
						if (!check_key(key)) {
 | 
				
			||||||
 | 
							// Check that we dont exceed buffer length
 | 
				
			||||||
 | 
							int insert = find_key(0);
 | 
				
			||||||
 | 
							if (insert < KEY_STATE_MAX_LENGTH) {
 | 
				
			||||||
 | 
								key_state_array[insert] = key;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void release_key(keycode key) {
 | 
				
			||||||
 | 
						uint8_t index = find_key(key);
 | 
				
			||||||
 | 
						if (index < KEY_STATE_MAX_LENGTH) {
 | 
				
			||||||
 | 
							// shift it over and remove key
 | 
				
			||||||
 | 
							key_state_array[index] = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct pointer_state pointer_state = {0, 0, {0, 0}, {0, 0, 0, 0}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct wlc_geometry saved_floating;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void start_floating(swayc_t *view) {
 | 
				
			||||||
 | 
						if (view->is_floating) {
 | 
				
			||||||
 | 
							saved_floating.origin.x = view->x;
 | 
				
			||||||
 | 
							saved_floating.origin.y = view->y;
 | 
				
			||||||
 | 
							saved_floating.size.w = view->width;
 | 
				
			||||||
 | 
							saved_floating.size.h = view->height;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void reset_floating(swayc_t *view) {
 | 
				
			||||||
 | 
						if (view->is_floating) {
 | 
				
			||||||
 | 
							view->x = saved_floating.origin.x;
 | 
				
			||||||
 | 
							view->y = saved_floating.origin.y;
 | 
				
			||||||
 | 
							view->width = saved_floating.size.w;
 | 
				
			||||||
 | 
							view->height = saved_floating.size.h;
 | 
				
			||||||
 | 
							arrange_windows(view->parent, -1, -1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pointer_state.floating = (struct pointer_floating){0,0};
 | 
				
			||||||
 | 
						pointer_state.lock = (struct pointer_lock){0,0,0,0};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										321
									
								
								sway/ipc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								sway/ipc.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,321 @@
 | 
				
			||||||
 | 
					// See https://i3wm.org/docs/ipc.html for protocol information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <sys/un.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stropts.h>
 | 
				
			||||||
 | 
					#include <sys/ioctl.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include "ipc.h"
 | 
				
			||||||
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "commands.h"
 | 
				
			||||||
 | 
					#include "list.h"
 | 
				
			||||||
 | 
					#include "stringop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ipc_socket = -1;
 | 
				
			||||||
 | 
					static struct wlc_event_source *ipc_event_source =  NULL;
 | 
				
			||||||
 | 
					static struct sockaddr_un ipc_sockaddr = {
 | 
				
			||||||
 | 
						.sun_family = AF_UNIX,
 | 
				
			||||||
 | 
						.sun_path = "/tmp/sway-ipc.sock"
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipc_client {
 | 
				
			||||||
 | 
						struct wlc_event_source *event_source;
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
						uint32_t payload_length;
 | 
				
			||||||
 | 
						enum ipc_command_type current_command;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipc_handle_connection(int fd, uint32_t mask, void *data);
 | 
				
			||||||
 | 
					int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data);
 | 
				
			||||||
 | 
					void ipc_client_disconnect(struct ipc_client *client);
 | 
				
			||||||
 | 
					void ipc_client_handle_command(struct ipc_client *client);
 | 
				
			||||||
 | 
					bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length);
 | 
				
			||||||
 | 
					void ipc_get_workspaces_callback(swayc_t *container, void *data);
 | 
				
			||||||
 | 
					void ipc_get_outputs_callback(swayc_t *container, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *json_list(list_t *items);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_init(void) {
 | 
				
			||||||
 | 
						ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
 | 
				
			||||||
 | 
						if (ipc_socket == -1) {
 | 
				
			||||||
 | 
							sway_abort("Unable to create IPC socket");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (getenv("SWAYSOCK") != NULL) {
 | 
				
			||||||
 | 
							strncpy(ipc_sockaddr.sun_path, getenv("SWAYSOCK"), sizeof(ipc_sockaddr.sun_path));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unlink(ipc_sockaddr.sun_path);
 | 
				
			||||||
 | 
						if (bind(ipc_socket, (struct sockaddr *)&ipc_sockaddr, sizeof(ipc_sockaddr)) == -1) {
 | 
				
			||||||
 | 
							sway_abort("Unable to bind IPC socket");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (listen(ipc_socket, 3) == -1) {
 | 
				
			||||||
 | 
							sway_abort("Unable to listen on IPC socket");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set i3 IPC socket path so that i3-msg works out of the box
 | 
				
			||||||
 | 
						setenv("I3SOCK", ipc_sockaddr.sun_path, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipc_event_source = wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_terminate(void) {
 | 
				
			||||||
 | 
						if (ipc_event_source) {
 | 
				
			||||||
 | 
							wlc_event_source_remove(ipc_event_source);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						close(ipc_socket);
 | 
				
			||||||
 | 
						unlink(ipc_sockaddr.sun_path);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipc_handle_connection(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
 | 
						(void) fd; (void) data;
 | 
				
			||||||
 | 
						sway_log(L_DEBUG, "Event on IPC listening socket");
 | 
				
			||||||
 | 
						assert(mask == WLC_EVENT_READABLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int client_fd = accept(ipc_socket, NULL, NULL);
 | 
				
			||||||
 | 
						if (client_fd == -1) {
 | 
				
			||||||
 | 
							sway_log_errno(L_INFO, "Unable to accept IPC client connection");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int flags;
 | 
				
			||||||
 | 
						if ((flags=fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) {
 | 
				
			||||||
 | 
							sway_log_errno(L_INFO, "Unable to set CLOEXEC on IPC client socket");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ipc_client* client = malloc(sizeof(struct ipc_client));
 | 
				
			||||||
 | 
						client->payload_length = 0;
 | 
				
			||||||
 | 
						client->fd = client_fd;
 | 
				
			||||||
 | 
						client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int ipc_header_size = sizeof(ipc_magic)+8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
 | 
				
			||||||
 | 
						struct ipc_client *client = data;
 | 
				
			||||||
 | 
						sway_log(L_DEBUG, "Event on IPC client socket %d", client_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mask & WLC_EVENT_ERROR) {
 | 
				
			||||||
 | 
							sway_log(L_INFO, "IPC Client socket error, removing client");
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mask & WLC_EVENT_HANGUP) {
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int read_available;
 | 
				
			||||||
 | 
						ioctl(client_fd, FIONREAD, &read_available);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Wait for the rest of the command payload in case the header has already been read
 | 
				
			||||||
 | 
						if (client->payload_length > 0) {
 | 
				
			||||||
 | 
							if (read_available >= client->payload_length) {
 | 
				
			||||||
 | 
								ipc_client_handle_command(client);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								sway_log(L_DEBUG, "Too little data to read payload on IPC Client socket, waiting for more (%d < %d)", read_available, client->payload_length);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (read_available < ipc_header_size) {
 | 
				
			||||||
 | 
							sway_log(L_DEBUG, "Too little data to read header on IPC Client socket, waiting for more (%d < %d)", read_available, ipc_header_size);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char buf[ipc_header_size];
 | 
				
			||||||
 | 
						ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
 | 
				
			||||||
 | 
						if (received == -1) {
 | 
				
			||||||
 | 
							sway_log_errno(L_INFO, "Unable to receive header from IPC client");
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) {
 | 
				
			||||||
 | 
							sway_log(L_DEBUG, "IPC header check failed");
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client->payload_length = *(uint32_t *)&buf[sizeof(ipc_magic)];
 | 
				
			||||||
 | 
						client->current_command = (enum ipc_command_type) *(uint32_t *)&buf[sizeof(ipc_magic)+4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (read_available - received >= client->payload_length) {
 | 
				
			||||||
 | 
							ipc_client_handle_command(client);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_client_disconnect(struct ipc_client *client)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!sway_assert(client != NULL, "client != NULL")) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sway_log(L_INFO, "IPC Client %d disconnected", client->fd);
 | 
				
			||||||
 | 
						wlc_event_source_remove(client->event_source);
 | 
				
			||||||
 | 
						close(client->fd);
 | 
				
			||||||
 | 
						free(client);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
 | 
						if (!sway_assert(client != NULL, "client != NULL")) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char buf[client->payload_length + 1];
 | 
				
			||||||
 | 
						if (client->payload_length > 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ssize_t received = recv(client->fd, buf, client->payload_length, 0);
 | 
				
			||||||
 | 
							if (received == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								sway_log_errno(L_INFO, "Unable to receive payload from IPC client");
 | 
				
			||||||
 | 
								ipc_client_disconnect(client);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (client->current_command) {
 | 
				
			||||||
 | 
						case IPC_COMMAND:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							buf[client->payload_length] = '\0';
 | 
				
			||||||
 | 
							bool success = handle_command(config, buf);
 | 
				
			||||||
 | 
							char reply[64];
 | 
				
			||||||
 | 
							int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false");
 | 
				
			||||||
 | 
							ipc_send_reply(client, reply, (uint32_t) length);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						case IPC_GET_WORKSPACES:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							list_t *workspaces = create_list();
 | 
				
			||||||
 | 
							container_map(&root_container, ipc_get_workspaces_callback, workspaces);
 | 
				
			||||||
 | 
							char *json = json_list(workspaces);
 | 
				
			||||||
 | 
							free_flat_list(workspaces);
 | 
				
			||||||
 | 
							ipc_send_reply(client, json, strlen(json));
 | 
				
			||||||
 | 
							free(json);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						case IPC_GET_OUTPUTS:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							list_t *outputs = create_list();
 | 
				
			||||||
 | 
							container_map(&root_container, ipc_get_outputs_callback, outputs);
 | 
				
			||||||
 | 
							char *json = json_list(outputs);
 | 
				
			||||||
 | 
							free_flat_list(outputs);
 | 
				
			||||||
 | 
							ipc_send_reply(client, json, strlen(json));
 | 
				
			||||||
 | 
							free(json);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							sway_log(L_INFO, "Unknown IPC command type %i", client->current_command);
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client->payload_length = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) {
 | 
				
			||||||
 | 
						assert(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char data[ipc_header_size];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(data, ipc_magic, sizeof(ipc_magic));
 | 
				
			||||||
 | 
						*(uint32_t *)&(data[sizeof(ipc_magic)]) = payload_length;
 | 
				
			||||||
 | 
						*(uint32_t *)&(data[sizeof(ipc_magic)+4]) = client->current_command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (write(client->fd, data, ipc_header_size) == -1) {
 | 
				
			||||||
 | 
							sway_log_errno(L_INFO, "Unable to send header to IPC client");
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (write(client->fd, payload, payload_length) == -1) {
 | 
				
			||||||
 | 
							sway_log_errno(L_INFO, "Unable to send payload to IPC client");
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *json_list(list_t *items) {
 | 
				
			||||||
 | 
						char *json_elements = join_list(items, ",");
 | 
				
			||||||
 | 
						size_t len = strlen(json_elements);
 | 
				
			||||||
 | 
						char *json = malloc(len + 3);
 | 
				
			||||||
 | 
						json[0] = '[';
 | 
				
			||||||
 | 
						memcpy(json + 1, json_elements, len);
 | 
				
			||||||
 | 
						json[len+1] = ']';
 | 
				
			||||||
 | 
						json[len+2] = '\0';
 | 
				
			||||||
 | 
						free(json_elements);
 | 
				
			||||||
 | 
						return json;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_get_workspaces_callback(swayc_t *container, void *data) {
 | 
				
			||||||
 | 
						if (container->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
							char *json = malloc(512); // Output should usually be around 180 chars
 | 
				
			||||||
 | 
							int num = isdigit(container->name[0]) ? atoi(container->name) : -1;
 | 
				
			||||||
 | 
							// TODO: escape the name (quotation marks, unicode)
 | 
				
			||||||
 | 
							sprintf(json,
 | 
				
			||||||
 | 
								"{"
 | 
				
			||||||
 | 
									"\"num\":%d,"
 | 
				
			||||||
 | 
									"\"name\":\"%s\","
 | 
				
			||||||
 | 
									"\"visible\":%s,"
 | 
				
			||||||
 | 
									"\"focused\":%s,"
 | 
				
			||||||
 | 
									"\"rect\":{"
 | 
				
			||||||
 | 
										"\"x\":%d,"
 | 
				
			||||||
 | 
										"\"y\":%d,"
 | 
				
			||||||
 | 
										"\"width\":%d,"
 | 
				
			||||||
 | 
										"\"height\":%d"
 | 
				
			||||||
 | 
									"},"
 | 
				
			||||||
 | 
									"\"output\":\"%s\","
 | 
				
			||||||
 | 
									"\"urgent\":%s"
 | 
				
			||||||
 | 
								"}",
 | 
				
			||||||
 | 
								num, container->name, container->visible ? "true" : "false", container->is_focused ? "true" : "false",
 | 
				
			||||||
 | 
								container->x, container->y, container->width, container->height,
 | 
				
			||||||
 | 
								container->parent->name, "false" // TODO: urgent hint
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							list_add((list_t *)data, json);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipc_get_outputs_callback(swayc_t *container, void *data) {
 | 
				
			||||||
 | 
						if (container->type == C_OUTPUT) {
 | 
				
			||||||
 | 
							char *json = malloc(512); // Output should usually be around 130 chars
 | 
				
			||||||
 | 
							// TODO: escape the name (quotation marks, unicode)
 | 
				
			||||||
 | 
							sprintf(json,
 | 
				
			||||||
 | 
								"{"
 | 
				
			||||||
 | 
									"\"name\":\"%s\","
 | 
				
			||||||
 | 
									"\"active\":%s,"
 | 
				
			||||||
 | 
									"\"primary\":%s,"
 | 
				
			||||||
 | 
									"\"rect\":{"
 | 
				
			||||||
 | 
										"\"x\":%d,"
 | 
				
			||||||
 | 
										"\"y\":%d,"
 | 
				
			||||||
 | 
										"\"width\":%d,"
 | 
				
			||||||
 | 
										"\"height\":%d"
 | 
				
			||||||
 | 
									"},"
 | 
				
			||||||
 | 
									"\"current_workspace\":\"%s\""
 | 
				
			||||||
 | 
								"}",
 | 
				
			||||||
 | 
								container->name, "true", "false", // TODO: active, primary
 | 
				
			||||||
 | 
								container->x, container->y, container->width, container->height,
 | 
				
			||||||
 | 
								container->focused ? container->focused->name : ""
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							list_add((list_t *)data, json);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										186
									
								
								sway/layout.c
									
										
									
									
									
								
							
							
						
						
									
										186
									
								
								sway/layout.c
									
										
									
									
									
								
							| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include "layout.h"
 | 
					#include "layout.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
#include "container.h"
 | 
					#include "container.h"
 | 
				
			||||||
#include "workspace.h"
 | 
					#include "workspace.h"
 | 
				
			||||||
#include "focus.h"
 | 
					#include "focus.h"
 | 
				
			||||||
| 
						 | 
					@ -32,6 +33,21 @@ void add_child(swayc_t *parent, swayc_t *child) {
 | 
				
			||||||
		child->width, child->height, parent, parent->type, parent->width, parent->height);
 | 
							child->width, child->height, parent, parent->type, parent->width, parent->height);
 | 
				
			||||||
	list_add(parent->children, child);
 | 
						list_add(parent->children, child);
 | 
				
			||||||
	child->parent = parent;
 | 
						child->parent = parent;
 | 
				
			||||||
 | 
						// set focus for this container
 | 
				
			||||||
 | 
						if (parent->children->length == 1) {
 | 
				
			||||||
 | 
							set_focused_container_for(parent, child);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void add_floating(swayc_t *ws, swayc_t *child) {
 | 
				
			||||||
 | 
						sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type,
 | 
				
			||||||
 | 
							child->width, child->height, ws, ws->type, ws->width, ws->height);
 | 
				
			||||||
 | 
						list_add(ws->floating, child);
 | 
				
			||||||
 | 
						child->parent = ws;
 | 
				
			||||||
 | 
						child->is_floating = true;
 | 
				
			||||||
 | 
						if (!ws->focused) {
 | 
				
			||||||
 | 
							set_focused_container_for(ws, child);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) {
 | 
					swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) {
 | 
				
			||||||
| 
						 | 
					@ -55,7 +71,7 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) {
 | 
				
			||||||
	new_child->parent = child->parent;
 | 
						new_child->parent = child->parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (child->parent->focused == child) {
 | 
						if (child->parent->focused == child) {
 | 
				
			||||||
		child->parent->focused = new_child;
 | 
							set_focused_container_for(child->parent, new_child);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	child->parent = NULL;
 | 
						child->parent = NULL;
 | 
				
			||||||
	return parent;
 | 
						return parent;
 | 
				
			||||||
| 
						 | 
					@ -72,6 +88,7 @@ swayc_t *remove_child(swayc_t *child) {
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							i = 0;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		for (i = 0; i < parent->children->length; ++i) {
 | 
							for (i = 0; i < parent->children->length; ++i) {
 | 
				
			||||||
			if (parent->children->items[i] == child) {
 | 
								if (parent->children->items[i] == child) {
 | 
				
			||||||
| 
						 | 
					@ -80,7 +97,7 @@ swayc_t *remove_child(swayc_t *child) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	//Set focused to new container
 | 
						// Set focused to new container
 | 
				
			||||||
	if (parent->focused == child) {
 | 
						if (parent->focused == child) {
 | 
				
			||||||
		if (parent->children->length > 0) {
 | 
							if (parent->children->length > 0) {
 | 
				
			||||||
			set_focused_container_for(parent, parent->children->items[i?i-1:0]);
 | 
								set_focused_container_for(parent, parent->children->items[i?i-1:0]);
 | 
				
			||||||
| 
						 | 
					@ -104,7 +121,7 @@ void move_container(swayc_t *container,swayc_t* root,int direction){
 | 
				
			||||||
				//Only one container, meh.
 | 
									//Only one container, meh.
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								//TODO: Implement horizontal movement.
 | 
				
			||||||
			//TODO: Implement move to a different workspace.
 | 
								//TODO: Implement move to a different workspace.
 | 
				
			||||||
			if(direction == MOVE_LEFT && i > 0){
 | 
								if(direction == MOVE_LEFT && i > 0){
 | 
				
			||||||
				temp = root->children->items[i-1];
 | 
									temp = root->children->items[i-1];
 | 
				
			||||||
| 
						 | 
					@ -167,11 +184,11 @@ void arrange_windows(swayc_t *container, int width, int height) {
 | 
				
			||||||
		// y -= container->y;
 | 
							// y -= container->y;
 | 
				
			||||||
		for (i = 0; i < container->children->length; ++i) {
 | 
							for (i = 0; i < container->children->length; ++i) {
 | 
				
			||||||
			swayc_t *child = container->children->items[i];
 | 
								swayc_t *child = container->children->items[i];
 | 
				
			||||||
			sway_log(L_DEBUG, "Arranging workspace #%d", i);
 | 
								child->x = x + container->gaps;
 | 
				
			||||||
			child->x = x;
 | 
								child->y = y + container->gaps;
 | 
				
			||||||
			child->y = y;
 | 
								child->width = width - container->gaps * 2;
 | 
				
			||||||
			child->width = width;
 | 
								child->height = height - container->gaps * 2;
 | 
				
			||||||
			child->height = height;
 | 
								sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y);
 | 
				
			||||||
			arrange_windows(child, -1, -1);
 | 
								arrange_windows(child, -1, -1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -179,27 +196,24 @@ void arrange_windows(swayc_t *container, int width, int height) {
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			struct wlc_geometry geometry = {
 | 
								struct wlc_geometry geometry = {
 | 
				
			||||||
				.origin = {
 | 
									.origin = {
 | 
				
			||||||
					.x = container->x,
 | 
										.x = container->x + container->gaps / 2,
 | 
				
			||||||
					.y = container->y
 | 
										.y = container->y + container->gaps / 2
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				.size = {
 | 
									.size = {
 | 
				
			||||||
					.w = width,
 | 
										.w = width - container->gaps,
 | 
				
			||||||
					.h = height
 | 
										.h = height - container->gaps
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) {
 | 
								if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) {
 | 
				
			||||||
				swayc_t *parent = container;
 | 
									swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT);
 | 
				
			||||||
				while (parent->type != C_OUTPUT) {
 | 
					 | 
				
			||||||
					parent = parent->parent;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				geometry.origin.x = 0;
 | 
									geometry.origin.x = 0;
 | 
				
			||||||
				geometry.origin.y = 0;
 | 
									geometry.origin.y = 0;
 | 
				
			||||||
				geometry.size.w = parent->width;
 | 
									geometry.size.w = parent->width;
 | 
				
			||||||
				geometry.size.h = parent->height;
 | 
									geometry.size.h = parent->height;
 | 
				
			||||||
				wlc_view_set_geometry(container->handle, &geometry);
 | 
									wlc_view_set_geometry(container->handle, 0, &geometry);
 | 
				
			||||||
				wlc_view_bring_to_front(container->handle);
 | 
									wlc_view_bring_to_front(container->handle);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				wlc_view_set_geometry(container->handle, &geometry);
 | 
									wlc_view_set_geometry(container->handle, 0, &geometry);
 | 
				
			||||||
				container->width = width;
 | 
									container->width = width;
 | 
				
			||||||
				container->height = height;
 | 
									container->height = height;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -213,40 +227,62 @@ void arrange_windows(swayc_t *container, int width, int height) {
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	double total_weight = 0;
 | 
						x = y = 0;
 | 
				
			||||||
	for (i = 0; i < container->children->length; ++i) {
 | 
						double scale = 0;
 | 
				
			||||||
		swayc_t *child = container->children->items[i];
 | 
					 | 
				
			||||||
		total_weight += child->weight;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (container->layout) {
 | 
						switch (container->layout) {
 | 
				
			||||||
	case L_HORIZ:
 | 
						case L_HORIZ:
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		sway_log(L_DEBUG, "Arranging %p horizontally", container);
 | 
							// Calculate total width
 | 
				
			||||||
		for (i = 0; i < container->children->length; ++i) {
 | 
							for (i = 0; i < container->children->length; ++i) {
 | 
				
			||||||
			swayc_t *child = container->children->items[i];
 | 
								int *old_width = &((swayc_t *)container->children->items[i])->width;
 | 
				
			||||||
			double percent = child->weight / total_weight;
 | 
								if (*old_width <= 0) {
 | 
				
			||||||
			sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will receive %.2f of %d)", child, child->type, percent, width);
 | 
									if (container->children->length > 1) {
 | 
				
			||||||
			child->x = x + container->x;
 | 
										*old_width = width / (container->children->length - 1);
 | 
				
			||||||
			child->y = y + container->y;
 | 
									} else {
 | 
				
			||||||
			int w = width * percent;
 | 
										*old_width = width;
 | 
				
			||||||
			int h = height;
 | 
									}
 | 
				
			||||||
			arrange_windows(child, w, h);
 | 
								}
 | 
				
			||||||
			x += w;
 | 
								scale += *old_width;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Resize windows
 | 
				
			||||||
 | 
							if (scale > 0.1) {
 | 
				
			||||||
 | 
								scale = width / scale;
 | 
				
			||||||
 | 
								sway_log(L_DEBUG, "Arranging %p horizontally", container);
 | 
				
			||||||
 | 
								for (i = 0; i < container->children->length; ++i) {
 | 
				
			||||||
 | 
									swayc_t *child = container->children->items[i];
 | 
				
			||||||
 | 
									sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, width, scale);
 | 
				
			||||||
 | 
									child->x = x + container->x;
 | 
				
			||||||
 | 
									child->y = y + container->y;
 | 
				
			||||||
 | 
									arrange_windows(child, child->width * scale, height);
 | 
				
			||||||
 | 
									x += child->width;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case L_VERT:
 | 
						case L_VERT:
 | 
				
			||||||
		sway_log(L_DEBUG, "Arranging %p vertically", container);
 | 
							// Calculate total height
 | 
				
			||||||
		for (i = 0; i < container->children->length; ++i) {
 | 
							for (i = 0; i < container->children->length; ++i) {
 | 
				
			||||||
			swayc_t *child = container->children->items[i];
 | 
								int *old_height = &((swayc_t *)container->children->items[i])->height;
 | 
				
			||||||
			double percent = child->weight / total_weight;
 | 
								if (*old_height <= 0) {
 | 
				
			||||||
			sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will receive %.2f of %d)", child, child->type, percent, width);
 | 
									if (container->children->length > 1) {
 | 
				
			||||||
			child->x = x + container->x;
 | 
										*old_height = height / (container->children->length - 1);
 | 
				
			||||||
			child->y = y + container->y;
 | 
									} else {
 | 
				
			||||||
			int w = width;
 | 
										*old_height = height;
 | 
				
			||||||
			int h = height * percent;
 | 
									}
 | 
				
			||||||
			arrange_windows(child, w, h);
 | 
								}
 | 
				
			||||||
			y += h;
 | 
								scale += *old_height;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Resize
 | 
				
			||||||
 | 
							if (scale > 0.1) {
 | 
				
			||||||
 | 
								scale = height / scale;
 | 
				
			||||||
 | 
								sway_log(L_DEBUG, "Arranging %p vertically", container);
 | 
				
			||||||
 | 
								for (i = 0; i < container->children->length; ++i) {
 | 
				
			||||||
 | 
									swayc_t *child = container->children->items[i];
 | 
				
			||||||
 | 
									sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, height, scale);
 | 
				
			||||||
 | 
									child->x = x + container->x;
 | 
				
			||||||
 | 
									child->y = y + container->y;
 | 
				
			||||||
 | 
									arrange_windows(child, width, child->height * scale);
 | 
				
			||||||
 | 
									y += child->height;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -268,20 +304,15 @@ void arrange_windows(swayc_t *container, int width, int height) {
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				};
 | 
									};
 | 
				
			||||||
				if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) {
 | 
									if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) {
 | 
				
			||||||
					swayc_t *parent = view;
 | 
										swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
 | 
				
			||||||
					while (parent->type != C_OUTPUT) {
 | 
					 | 
				
			||||||
						parent = parent->parent;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					geometry.origin.x = 0;
 | 
										geometry.origin.x = 0;
 | 
				
			||||||
					geometry.origin.y = 0;
 | 
										geometry.origin.y = 0;
 | 
				
			||||||
					geometry.size.w = parent->width;
 | 
										geometry.size.w = parent->width;
 | 
				
			||||||
					geometry.size.h = parent->height;
 | 
										geometry.size.h = parent->height;
 | 
				
			||||||
					wlc_view_set_geometry(view->handle, &geometry);
 | 
										wlc_view_set_geometry(view->handle, 0, &geometry);
 | 
				
			||||||
					wlc_view_bring_to_front(view->handle);
 | 
										wlc_view_bring_to_front(view->handle);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					wlc_view_set_geometry(view->handle, &geometry);
 | 
										wlc_view_set_geometry(view->handle, 0, &geometry);
 | 
				
			||||||
					view->width = width;
 | 
					 | 
				
			||||||
					view->height = height;
 | 
					 | 
				
			||||||
					// Bring the views to the front in order of the list, the list
 | 
										// Bring the views to the front in order of the list, the list
 | 
				
			||||||
					// will be kept up to date so that more recently focused views
 | 
										// will be kept up to date so that more recently focused views
 | 
				
			||||||
					// have higher indexes
 | 
										// have higher indexes
 | 
				
			||||||
| 
						 | 
					@ -326,3 +357,54 @@ swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) {
 | 
				
			||||||
 | 
						swayc_t *parent = container->parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dir == MOVE_PARENT) {
 | 
				
			||||||
 | 
							if (parent->type == C_OUTPUT) {
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return parent;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						while (true) {
 | 
				
			||||||
 | 
							// Test if we can even make a difference here
 | 
				
			||||||
 | 
							bool can_move = false;
 | 
				
			||||||
 | 
							int diff = 0;
 | 
				
			||||||
 | 
							if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
 | 
				
			||||||
 | 
								if (parent->layout == L_HORIZ || parent->type == C_ROOT) {
 | 
				
			||||||
 | 
									can_move = true;
 | 
				
			||||||
 | 
									diff = dir == MOVE_LEFT ? -1 : 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (parent->layout == L_VERT) {
 | 
				
			||||||
 | 
									can_move = true;
 | 
				
			||||||
 | 
									diff = dir == MOVE_UP ? -1 : 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (can_move) {
 | 
				
			||||||
 | 
								int i;
 | 
				
			||||||
 | 
								for (i = 0; i < parent->children->length; ++i) {
 | 
				
			||||||
 | 
									swayc_t *child = parent->children->items[i];
 | 
				
			||||||
 | 
									if (child == container) {
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								int desired = i + diff;
 | 
				
			||||||
 | 
								if (desired < 0 || desired >= parent->children->length) {
 | 
				
			||||||
 | 
									can_move = false;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return parent->children->items[desired];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (!can_move) {
 | 
				
			||||||
 | 
								container = parent;
 | 
				
			||||||
 | 
								parent = parent->parent;
 | 
				
			||||||
 | 
								if (!parent) {
 | 
				
			||||||
 | 
									// Nothing we can do
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										117
									
								
								sway/log.c
									
										
									
									
									
								
							
							
						
						
									
										117
									
								
								sway/log.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,9 +1,13 @@
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "sway.h"
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int colored = 1;
 | 
					int colored = 1;
 | 
				
			||||||
int v = 0;
 | 
					int v = 0;
 | 
				
			||||||
| 
						 | 
					@ -18,10 +22,10 @@ static const char *verbosity_colors[] = {
 | 
				
			||||||
void init_log(int verbosity) {
 | 
					void init_log(int verbosity) {
 | 
				
			||||||
	v = verbosity;
 | 
						v = verbosity;
 | 
				
			||||||
	/* set FD_CLOEXEC flag to prevent programs called with exec to write into logs */
 | 
						/* set FD_CLOEXEC flag to prevent programs called with exec to write into logs */
 | 
				
			||||||
	int i, flag;
 | 
						int i;
 | 
				
			||||||
	int fd[] = { STDOUT_FILENO, STDIN_FILENO, STDERR_FILENO };
 | 
						int fd[] = { STDOUT_FILENO, STDIN_FILENO, STDERR_FILENO };
 | 
				
			||||||
	for (i = 0; i < 3; ++i) {
 | 
						for (i = 0; i < 3; ++i) {
 | 
				
			||||||
		flag = fcntl(fd[i], F_GETFD);
 | 
							int flag = fcntl(fd[i], F_GETFD);
 | 
				
			||||||
		if (flag != -1) {
 | 
							if (flag != -1) {
 | 
				
			||||||
			fcntl(fd[i], F_SETFD, flag | FD_CLOEXEC);
 | 
								fcntl(fd[i], F_SETFD, flag | FD_CLOEXEC);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -32,17 +36,17 @@ void sway_log_colors(int mode) {
 | 
				
			||||||
	colored = (mode == 1) ? 1 : 0;
 | 
						colored = (mode == 1) ? 1 : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sway_abort(char *format, ...) {
 | 
					void sway_abort(const char *format, ...) {
 | 
				
			||||||
	fprintf(stderr, "ERROR: ");
 | 
						fprintf(stderr, "ERROR: ");
 | 
				
			||||||
	va_list args;
 | 
						va_list args;
 | 
				
			||||||
	va_start(args, format);
 | 
						va_start(args, format);
 | 
				
			||||||
	vfprintf(stderr, format, args);
 | 
						vfprintf(stderr, format, args);
 | 
				
			||||||
	va_end(args);
 | 
						va_end(args);
 | 
				
			||||||
	fprintf(stderr, "\n");
 | 
						fprintf(stderr, "\n");
 | 
				
			||||||
	exit(1);
 | 
						sway_terminate();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sway_log(int verbosity, char* format, ...) {
 | 
					void sway_log(int verbosity, const char* format, ...) {
 | 
				
			||||||
	if (verbosity <= v) {
 | 
						if (verbosity <= v) {
 | 
				
			||||||
		int c = verbosity;
 | 
							int c = verbosity;
 | 
				
			||||||
		if (c > sizeof(verbosity_colors) / sizeof(char *)) {
 | 
							if (c > sizeof(verbosity_colors) / sizeof(char *)) {
 | 
				
			||||||
| 
						 | 
					@ -64,3 +68,106 @@ void sway_log(int verbosity, char* format, ...) {
 | 
				
			||||||
		fprintf(stderr, "\n");
 | 
							fprintf(stderr, "\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sway_log_errno(int verbosity, char* format, ...) {
 | 
				
			||||||
 | 
						if (verbosity <= v) {
 | 
				
			||||||
 | 
							int c = verbosity;
 | 
				
			||||||
 | 
							if (c > sizeof(verbosity_colors) / sizeof(char *)) {
 | 
				
			||||||
 | 
								c = sizeof(verbosity_colors) / sizeof(char *) - 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (colored) {
 | 
				
			||||||
 | 
								fprintf(stderr, verbosity_colors[c]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							va_list args;
 | 
				
			||||||
 | 
							va_start(args, format);
 | 
				
			||||||
 | 
							vfprintf(stderr, format, args);
 | 
				
			||||||
 | 
							va_end(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fprintf(stderr, ": ");
 | 
				
			||||||
 | 
							char error[256];
 | 
				
			||||||
 | 
							strerror_r(errno, error, sizeof(error));
 | 
				
			||||||
 | 
							fprintf(stderr, error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (colored) {
 | 
				
			||||||
 | 
								fprintf(stderr, "\x1B[0m");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fprintf(stderr, "\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sway_assert(bool condition, const char* format, ...) {
 | 
				
			||||||
 | 
						if (condition) {
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
						raise(SIGABRT);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_list args;
 | 
				
			||||||
 | 
						va_start(args, format);
 | 
				
			||||||
 | 
						sway_log(L_ERROR, format, args);
 | 
				
			||||||
 | 
						va_end(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "workspace.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* XXX:DEBUG:XXX */
 | 
				
			||||||
 | 
					static void container_log(const swayc_t *c) {
 | 
				
			||||||
 | 
						fprintf(stderr, "focus:%c|",
 | 
				
			||||||
 | 
								c->is_focused ? 'F' : // Focused
 | 
				
			||||||
 | 
								c == active_workspace ? 'W' : // active workspace
 | 
				
			||||||
 | 
								c == &root_container  ? 'R' : // root
 | 
				
			||||||
 | 
								'X');// not any others
 | 
				
			||||||
 | 
						fprintf(stderr,"(%p)",c);
 | 
				
			||||||
 | 
						fprintf(stderr,"(p:%p)",c->parent);
 | 
				
			||||||
 | 
						fprintf(stderr,"(f:%p)",c->focused);
 | 
				
			||||||
 | 
						fprintf(stderr,"(h:%ld)",c->handle);
 | 
				
			||||||
 | 
						fprintf(stderr,"Type:");
 | 
				
			||||||
 | 
						fprintf(stderr,
 | 
				
			||||||
 | 
								c->type == C_ROOT   ? "Root|" :
 | 
				
			||||||
 | 
								c->type == C_OUTPUT ? "Output|" :
 | 
				
			||||||
 | 
								c->type == C_WORKSPACE ? "Workspace|" :
 | 
				
			||||||
 | 
								c->type == C_CONTAINER ? "Container|" :
 | 
				
			||||||
 | 
								c->type == C_VIEW   ? "View|" : "Unknown|");
 | 
				
			||||||
 | 
						fprintf(stderr,"layout:");
 | 
				
			||||||
 | 
						fprintf(stderr,
 | 
				
			||||||
 | 
								c->layout == L_NONE ? "NONE|" :
 | 
				
			||||||
 | 
								c->layout == L_HORIZ ? "Horiz|":
 | 
				
			||||||
 | 
								c->layout == L_VERT ? "Vert|":
 | 
				
			||||||
 | 
								c->layout == L_STACKED  ? "Stacked|":
 | 
				
			||||||
 | 
								c->layout == L_FLOATING ? "Floating|":
 | 
				
			||||||
 | 
								"Unknown|");
 | 
				
			||||||
 | 
						fprintf(stderr, "w:%d|h:%d|", c->width, c->height);
 | 
				
			||||||
 | 
						fprintf(stderr, "x:%d|y:%d|", c->x, c->y);
 | 
				
			||||||
 | 
						fprintf(stderr, "vis:%c|", c->visible?'t':'f');
 | 
				
			||||||
 | 
						fprintf(stderr, "name:%.16s|", c->name);
 | 
				
			||||||
 | 
						fprintf(stderr, "children:%d\n",c->children?c->children->length:0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void layout_log(const swayc_t *c, int depth) {
 | 
				
			||||||
 | 
						int i, d;
 | 
				
			||||||
 | 
						int e = c->children ? c->children->length : 0;
 | 
				
			||||||
 | 
						container_log(c);
 | 
				
			||||||
 | 
						if (e) {
 | 
				
			||||||
 | 
							for (i = 0; i < e; ++i) {
 | 
				
			||||||
 | 
								fputc('|',stderr);
 | 
				
			||||||
 | 
								for (d = 0; d < depth; ++d) fputc('-', stderr);
 | 
				
			||||||
 | 
								layout_log(c->children->items[i], depth + 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (c->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
							e = c->floating?c->floating->length:0;
 | 
				
			||||||
 | 
							if (e) {
 | 
				
			||||||
 | 
								for (i = 0; i < e; ++i) {
 | 
				
			||||||
 | 
									fputc('|',stderr);
 | 
				
			||||||
 | 
									for (d = 0; d < depth; ++d) fputc('=', stderr);
 | 
				
			||||||
 | 
									layout_log(c->floating->items[i], depth + 1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/* XXX:DEBUG:XXX */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										100
									
								
								sway/main.c
									
										
									
									
									
								
							
							
						
						
									
										100
									
								
								sway/main.c
									
										
									
									
									
								
							| 
						 | 
					@ -4,31 +4,121 @@
 | 
				
			||||||
#include <wlc/wlc.h>
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
#include <sys/wait.h>
 | 
					#include <sys/wait.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					#include <getopt.h>
 | 
				
			||||||
#include "layout.h"
 | 
					#include "layout.h"
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "handlers.h"
 | 
					#include "handlers.h"
 | 
				
			||||||
 | 
					#include "ipc.h"
 | 
				
			||||||
 | 
					#include "sway.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool terminate_request = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sway_terminate(void) {
 | 
				
			||||||
 | 
						terminate_request = true;
 | 
				
			||||||
 | 
						wlc_terminate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sigchld_handle(int signal);
 | 
					static void sigchld_handle(int signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv) {
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
 | 
						static int verbose = 0, debug = 0, validate = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static struct option long_options[] = {
 | 
				
			||||||
 | 
							{"config", required_argument, NULL, 'c'},
 | 
				
			||||||
 | 
							{"validate", no_argument, &validate, 1},
 | 
				
			||||||
 | 
							{"debug", no_argument, &debug, 1},
 | 
				
			||||||
 | 
							{"version", no_argument, NULL, 'v'},
 | 
				
			||||||
 | 
							{"verbose", no_argument, &verbose, 1},
 | 
				
			||||||
 | 
							{"get-socketpath", no_argument, NULL, 'p'},
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Signal handling */
 | 
						/* Signal handling */
 | 
				
			||||||
	signal(SIGCHLD, sigchld_handle);
 | 
						signal(SIGCHLD, sigchld_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setenv("WLC_DIM", "0", 0);
 | 
						setenv("WLC_DIM", "0", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FILE *devnull = fopen("/dev/null", "w");
 | 
				
			||||||
 | 
						if (devnull) {
 | 
				
			||||||
 | 
							// NOTE: Does not work, see wlc issue #54
 | 
				
			||||||
 | 
							wlc_set_log_file(devnull);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Changing code earlier than this point requires detailed review */
 | 
						/* Changing code earlier than this point requires detailed review */
 | 
				
			||||||
	if (!wlc_init(&interface, argc, argv)) {
 | 
						if (!wlc_init(&interface, argc, argv)) {
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_log(L_DEBUG); // TODO: Control this with command line arg
 | 
						char *config_path = NULL;
 | 
				
			||||||
	init_layout();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!load_config()) {
 | 
						int c;
 | 
				
			||||||
		sway_log(L_ERROR, "Error(s) loading config!");
 | 
						while (1) {
 | 
				
			||||||
 | 
							int option_index = 0;
 | 
				
			||||||
 | 
							c = getopt_long(argc, argv, "CdvVpc:", long_options, &option_index);
 | 
				
			||||||
 | 
							if (c == -1) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch (c) {
 | 
				
			||||||
 | 
							case 0: // Flag
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'c': // config
 | 
				
			||||||
 | 
								config_path = strdup(optarg);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'C': // validate
 | 
				
			||||||
 | 
								validate = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'd': // debug
 | 
				
			||||||
 | 
								debug = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'v': // version
 | 
				
			||||||
 | 
								// todo
 | 
				
			||||||
 | 
								exit(0);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'V': // verbose
 | 
				
			||||||
 | 
								verbose = 1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 'p': // --get-socketpath
 | 
				
			||||||
 | 
								// TODO
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlc_run();
 | 
						if (debug) {
 | 
				
			||||||
 | 
							init_log(L_DEBUG);
 | 
				
			||||||
 | 
							wlc_set_log_file(stderr);
 | 
				
			||||||
 | 
							fclose(devnull);
 | 
				
			||||||
 | 
							devnull = NULL;
 | 
				
			||||||
 | 
						} else if (verbose || validate) {
 | 
				
			||||||
 | 
							init_log(L_INFO);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							init_log(L_ERROR);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (validate) {
 | 
				
			||||||
 | 
							bool valid = load_config(config_path);
 | 
				
			||||||
 | 
							return valid ? 0 : 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_layout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!load_config(config_path)) {
 | 
				
			||||||
 | 
							sway_log(L_ERROR, "Error(s) loading config!");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (config_path) {
 | 
				
			||||||
 | 
							free(config_path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipc_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!terminate_request) {
 | 
				
			||||||
 | 
							wlc_run();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (devnull) {
 | 
				
			||||||
 | 
							fclose(devnull);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipc_terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,18 +17,22 @@ char *read_line(FILE *file) {
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (length == size) {
 | 
							if (length == size) {
 | 
				
			||||||
			string = realloc(string, size *= 2);
 | 
								char *new_string = realloc(string, size *= 2);
 | 
				
			||||||
			if (!string) {
 | 
								if (!new_string) {
 | 
				
			||||||
 | 
									free(string);
 | 
				
			||||||
				return NULL;
 | 
									return NULL;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								string = new_string;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		string[length++] = c;
 | 
							string[length++] = c;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (length + 1 == size) {
 | 
						if (length + 1 == size) {
 | 
				
			||||||
		string = realloc(string, length + 1);
 | 
							char *new_string = realloc(string, length + 1);
 | 
				
			||||||
		if (!string) {
 | 
							if (!new_string) {
 | 
				
			||||||
 | 
								free(string);
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							string = new_string;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	string[length] = '\0';
 | 
						string[length] = '\0';
 | 
				
			||||||
	return string;
 | 
						return string;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include "string.h"
 | 
					#include "string.h"
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include <strings.h>
 | 
					#include <strings.h>
 | 
				
			||||||
 | 
					#include <log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Note: This returns 8 characters for trimmed_start per tab character. */
 | 
					/* Note: This returns 8 characters for trimmed_start per tab character. */
 | 
				
			||||||
char *strip_whitespace(char *_str, int *trimmed_start) {
 | 
					char *strip_whitespace(char *_str, int *trimmed_start) {
 | 
				
			||||||
| 
						 | 
					@ -197,3 +198,41 @@ char *join_args(char **argv, int argc) {
 | 
				
			||||||
	res[len - 1] = '\0';
 | 
						res[len - 1] = '\0';
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Join a list of strings, adding separator in between. Separator can be NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					char *join_list(list_t *list, char *separator) {
 | 
				
			||||||
 | 
						if (!sway_assert(list != NULL, "list != NULL") || list->length == 0) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t len = 1; // NULL terminator
 | 
				
			||||||
 | 
						size_t sep_len = 0;
 | 
				
			||||||
 | 
						if (separator != NULL) {
 | 
				
			||||||
 | 
							sep_len = strlen(separator);
 | 
				
			||||||
 | 
							len += (list->length - 1) * sep_len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < list->length; i++) {
 | 
				
			||||||
 | 
							len += strlen(list->items[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *res = malloc(len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *p = res + strlen(list->items[0]);
 | 
				
			||||||
 | 
						strcpy(res, list->items[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 1; i < list->length; i++) {
 | 
				
			||||||
 | 
							if (sep_len) {
 | 
				
			||||||
 | 
								memcpy(p, separator, sep_len);
 | 
				
			||||||
 | 
								p += sep_len;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							strcpy(p, list->items[i]);
 | 
				
			||||||
 | 
							p += strlen(list->items[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*p = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ char *workspace_next_name(void) {
 | 
				
			||||||
			char* target = malloc(strlen(args->items[1]) + 1);
 | 
								char* target = malloc(strlen(args->items[1]) + 1);
 | 
				
			||||||
			strcpy(target, args->items[1]);
 | 
								strcpy(target, args->items[1]);
 | 
				
			||||||
			while (*target == ' ' || *target == '\t')
 | 
								while (*target == ' ' || *target == '\t')
 | 
				
			||||||
				target++; 
 | 
									target++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Make sure that the command references an actual workspace
 | 
								// Make sure that the command references an actual workspace
 | 
				
			||||||
			// not a command about workspaces
 | 
								// not a command about workspaces
 | 
				
			||||||
| 
						 | 
					@ -42,11 +42,15 @@ char *workspace_next_name(void) {
 | 
				
			||||||
				strcmp(target, "number") == 0 ||
 | 
									strcmp(target, "number") == 0 ||
 | 
				
			||||||
				strcmp(target, "back_and_forth") == 0 ||
 | 
									strcmp(target, "back_and_forth") == 0 ||
 | 
				
			||||||
				strcmp(target, "current") == 0)
 | 
									strcmp(target, "current") == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									list_free(args);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
		   
 | 
								}
 | 
				
			||||||
			//Make sure that the workspace doesn't already exist 
 | 
					
 | 
				
			||||||
 | 
								// Make sure that the workspace doesn't already exist
 | 
				
			||||||
			if (workspace_find_by_name(target)) {
 | 
								if (workspace_find_by_name(target)) {
 | 
				
			||||||
			   continue; 
 | 
									list_free(args);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			list_free(args);
 | 
								list_free(args);
 | 
				
			||||||
| 
						 | 
					@ -54,6 +58,7 @@ char *workspace_next_name(void) {
 | 
				
			||||||
			sway_log(L_DEBUG, "Workspace: Found free name %s", target);
 | 
								sway_log(L_DEBUG, "Workspace: Found free name %s", target);
 | 
				
			||||||
			return target;
 | 
								return target;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							list_free(args);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// As a fall back, get the current number of active workspaces
 | 
						// As a fall back, get the current number of active workspaces
 | 
				
			||||||
	// and return that + 1 for the next workspace's name
 | 
						// and return that + 1 for the next workspace's name
 | 
				
			||||||
| 
						 | 
					@ -70,14 +75,12 @@ char *workspace_next_name(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *workspace_create(const char* name) {
 | 
					swayc_t *workspace_create(const char* name) {
 | 
				
			||||||
	swayc_t *parent = get_focused_container(&root_container);
 | 
						swayc_t *parent = get_focused_container(&root_container);
 | 
				
			||||||
	while (parent->type != C_OUTPUT) {
 | 
						parent = swayc_parent_by_type(parent, C_OUTPUT);
 | 
				
			||||||
		parent = parent->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return new_workspace(parent, name);
 | 
						return new_workspace(parent, name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool workspace_by_name(swayc_t *view, void *data) {
 | 
					bool workspace_by_name(swayc_t *view, void *data) {
 | 
				
			||||||
	return (view->type == C_WORKSPACE) && 
 | 
						return (view->type == C_WORKSPACE) &&
 | 
				
			||||||
		   (strcasecmp(view->name, (char *) data) == 0);
 | 
							   (strcasecmp(view->name, (char *) data) == 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,62 +183,4 @@ void workspace_switch(swayc_t *workspace) {
 | 
				
			||||||
	sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name);
 | 
						sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name);
 | 
				
			||||||
	set_focused_container(get_focused_view(workspace));
 | 
						set_focused_container(get_focused_view(workspace));
 | 
				
			||||||
	arrange_windows(workspace, -1, -1);
 | 
						arrange_windows(workspace, -1, -1);
 | 
				
			||||||
	active_workspace = workspace;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/* XXX:DEBUG:XXX */
 | 
					 | 
				
			||||||
static void container_log(const swayc_t *c) {
 | 
					 | 
				
			||||||
	fprintf(stderr, "focus:%c|",
 | 
					 | 
				
			||||||
			c->is_focused ? 'F' : //Focused
 | 
					 | 
				
			||||||
			c == active_workspace ? 'W' : //active workspace
 | 
					 | 
				
			||||||
			c == &root_container  ? 'R' : //root
 | 
					 | 
				
			||||||
			'X');//not any others
 | 
					 | 
				
			||||||
	fprintf(stderr,"(%p)",c);
 | 
					 | 
				
			||||||
	fprintf(stderr,"(p:%p)",c->parent);
 | 
					 | 
				
			||||||
	fprintf(stderr,"(f:%p)",c->focused);
 | 
					 | 
				
			||||||
	fprintf(stderr,"(h:%ld)",c->handle);
 | 
					 | 
				
			||||||
	fprintf(stderr,"Type:");
 | 
					 | 
				
			||||||
	fprintf(stderr,
 | 
					 | 
				
			||||||
			c->type == C_ROOT   ? "Root|" :
 | 
					 | 
				
			||||||
			c->type == C_OUTPUT ? "Output|" :
 | 
					 | 
				
			||||||
			c->type == C_WORKSPACE ? "Workspace|" :
 | 
					 | 
				
			||||||
			c->type == C_CONTAINER ? "Container|" :
 | 
					 | 
				
			||||||
			c->type == C_VIEW   ? "View|" : "Unknown|");
 | 
					 | 
				
			||||||
	fprintf(stderr,"layout:");
 | 
					 | 
				
			||||||
	fprintf(stderr,
 | 
					 | 
				
			||||||
			c->layout == L_NONE ? "NONE|" :
 | 
					 | 
				
			||||||
			c->layout == L_HORIZ ? "Horiz|":
 | 
					 | 
				
			||||||
			c->layout == L_VERT ? "Vert|":
 | 
					 | 
				
			||||||
			c->layout == L_STACKED  ? "Stacked|":
 | 
					 | 
				
			||||||
			c->layout == L_FLOATING ? "Floating|":
 | 
					 | 
				
			||||||
			"Unknown|");
 | 
					 | 
				
			||||||
	fprintf(stderr, "w:%d|h:%d|", c->width, c->height);
 | 
					 | 
				
			||||||
	fprintf(stderr, "x:%d|y:%d|", c->x, c->y);
 | 
					 | 
				
			||||||
	fprintf(stderr, "vis:%c|", c->visible?'t':'f');
 | 
					 | 
				
			||||||
	fprintf(stderr, "wgt:%d|", c->weight);
 | 
					 | 
				
			||||||
	fprintf(stderr, "name:%.16s|", c->name);
 | 
					 | 
				
			||||||
	fprintf(stderr, "children:%d\n",c->children?c->children->length:0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void layout_log(const swayc_t *c, int depth) {
 | 
					 | 
				
			||||||
	int i, d;
 | 
					 | 
				
			||||||
	int e = c->children ? c->children->length : 0;
 | 
					 | 
				
			||||||
	container_log(c);
 | 
					 | 
				
			||||||
	if (e) {
 | 
					 | 
				
			||||||
		for (i = 0; i < e; ++i) {
 | 
					 | 
				
			||||||
			fputc('|',stderr);
 | 
					 | 
				
			||||||
			for (d = 0; d < depth; ++d) fputc('-', stderr);
 | 
					 | 
				
			||||||
			layout_log(c->children->items[i], depth + 1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (c->type == C_WORKSPACE) {
 | 
					 | 
				
			||||||
		e = c->floating?c->floating->length:0;
 | 
					 | 
				
			||||||
		if (e) {
 | 
					 | 
				
			||||||
			for (i = 0; i < e; ++i) {
 | 
					 | 
				
			||||||
				fputc('|',stderr);
 | 
					 | 
				
			||||||
				for (d = 0; d < depth; ++d) fputc('-', stderr);
 | 
					 | 
				
			||||||
				layout_log(c->floating->items[i], depth + 1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* XXX:DEBUG:XXX */
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue