mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	changed handling of focus, handling of view by type
This commit is contained in:
		
							parent
							
								
									780893a933
								
							
						
					
					
						commit
						11321ca2dd
					
				
					 12 changed files with 392 additions and 324 deletions
				
			
		| 
						 | 
					@ -45,6 +45,8 @@ struct sway_container {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool is_floating;
 | 
						bool is_floating;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool is_focused;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int weight;
 | 
						int weight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *name;
 | 
						char *name;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								include/focus.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								include/focus.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					#ifndef _SWAY_FOCUS_H
 | 
				
			||||||
 | 
					#define _SWAY_FOCUS_H
 | 
				
			||||||
 | 
					#include "container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum movement_direction {
 | 
				
			||||||
 | 
						MOVE_LEFT,
 | 
				
			||||||
 | 
						MOVE_RIGHT,
 | 
				
			||||||
 | 
						MOVE_UP,
 | 
				
			||||||
 | 
						MOVE_DOWN,
 | 
				
			||||||
 | 
						MOVE_PARENT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//focused_container - the container found by following the `focused` pointer
 | 
				
			||||||
 | 
					//from a given container to a container with `is_focused` boolean set
 | 
				
			||||||
 | 
					//---
 | 
				
			||||||
 | 
					//focused_view - the container found by following the `focused` pointer from a
 | 
				
			||||||
 | 
					//given container to a view.
 | 
				
			||||||
 | 
					//---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *get_focused_container(swayc_t *parent);
 | 
				
			||||||
 | 
					swayc_t *get_focused_view(swayc_t *parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void set_focused_container(swayc_t *container);
 | 
				
			||||||
 | 
					void set_focused_container_for(swayc_t *ancestor, swayc_t *container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//lock focused container/view. locked by windows with OVERRIDE attribute
 | 
				
			||||||
 | 
					//and unlocked when they are destroyed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern bool locked_container_focus;
 | 
				
			||||||
 | 
					extern bool locked_view_focus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool move_focus(enum movement_direction direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,11 @@
 | 
				
			||||||
#ifndef _SWAY_HANDLERS_H
 | 
					#ifndef _SWAY_HANDLERS_H
 | 
				
			||||||
#define _SWAY_HANDLERS_H
 | 
					#define _SWAY_HANDLERS_H
 | 
				
			||||||
 | 
					#include "container.h"
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <wlc/wlc.h>
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct wlc_interface interface;
 | 
					extern struct wlc_interface interface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//set focus to current pointer location and return focused container
 | 
					swayc_t *container_under_pointer(void);
 | 
				
			||||||
swayc_t *focus_pointer(void);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,17 +0,0 @@
 | 
				
			||||||
#ifndef _SWAY_MOVEMENT_H
 | 
					 | 
				
			||||||
#define _SWAY_MOVEMENT_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <wlc/wlc.h>
 | 
					 | 
				
			||||||
#include "list.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum movement_direction {
 | 
					 | 
				
			||||||
	MOVE_LEFT,
 | 
					 | 
				
			||||||
	MOVE_RIGHT,
 | 
					 | 
				
			||||||
	MOVE_UP,
 | 
					 | 
				
			||||||
	MOVE_DOWN,
 | 
					 | 
				
			||||||
	MOVE_PARENT
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool move_focus(enum movement_direction direction);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
#include "layout.h"
 | 
					#include "layout.h"
 | 
				
			||||||
#include "movement.h"
 | 
					#include "focus.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "workspace.h"
 | 
					#include "workspace.h"
 | 
				
			||||||
#include "commands.h"
 | 
					#include "commands.h"
 | 
				
			||||||
| 
						 | 
					@ -215,11 +215,12 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
			view->is_floating = false;
 | 
								view->is_floating = false;
 | 
				
			||||||
			active_workspace->focused = NULL;
 | 
								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 = focus_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
 | 
				
			||||||
			if (focused == NULL) {
 | 
								if (focused == NULL) {
 | 
				
			||||||
				focused = active_workspace;
 | 
									focused = active_workspace;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								set_focused_container(focused);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			sway_log(L_DEBUG, "Non-floating focused container is %p", focused);
 | 
								sway_log(L_DEBUG, "Non-floating focused container is %p", focused);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,7 +233,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) {
 | 
				
			||||||
				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
 | 
				
			||||||
			focus_view(view);
 | 
								set_focused_container(view);
 | 
				
			||||||
			arrange_windows(active_workspace, -1, -1);
 | 
								arrange_windows(active_workspace, -1, -1);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -345,7 +346,7 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		sway_log(L_DEBUG, "Adding new container around current focused container");
 | 
							sway_log(L_DEBUG, "Adding new container around current focused container");
 | 
				
			||||||
		swayc_t *parent = new_container(focused, layout);
 | 
							swayc_t *parent = new_container(focused, layout);
 | 
				
			||||||
		focus_view(focused);
 | 
							set_focused_container(focused);
 | 
				
			||||||
		arrange_windows(parent, -1, -1);
 | 
							arrange_windows(parent, -1, -1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,17 +39,11 @@ static void free_swayc(swayc_t *c) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* New containers */
 | 
					/* New containers */
 | 
				
			||||||
static void add_output_widths(swayc_t *container, void *_width) {
 | 
					 | 
				
			||||||
	int *width = _width;
 | 
					 | 
				
			||||||
	if (container->type == C_OUTPUT) {
 | 
					 | 
				
			||||||
		*width += container->width;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *new_output(wlc_handle handle) {
 | 
					swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
	const struct wlc_size* size = wlc_output_get_resolution(handle);
 | 
						const struct wlc_size* size = wlc_output_get_resolution(handle);
 | 
				
			||||||
	const char *name = wlc_output_get_name(handle);
 | 
						const char *name = wlc_output_get_name(handle);
 | 
				
			||||||
	sway_log(L_DEBUG, "Added output %u %s", (unsigned int)handle, name);
 | 
						sway_log(L_DEBUG, "Added output %lu:%s", handle, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	swayc_t *output = new_swayc(C_OUTPUT);
 | 
						swayc_t *output = new_swayc(C_OUTPUT);
 | 
				
			||||||
	output->width = size->w;
 | 
						output->width = size->w;
 | 
				
			||||||
| 
						 | 
					@ -59,9 +53,12 @@ swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	add_child(&root_container, output);
 | 
						add_child(&root_container, output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//TODO something with this
 | 
					//TODO still dont know why this is here?
 | 
				
			||||||
	int total_width = 0;
 | 
					//	int total_width = 0;
 | 
				
			||||||
	container_map(&root_container, add_output_widths, &total_width);
 | 
					//	int i;
 | 
				
			||||||
 | 
					//	for (i = 0; i < root_container.children->length; ++i) {
 | 
				
			||||||
 | 
					//		total_width += ((swayc_t*)root_container.children->items[i])->width;
 | 
				
			||||||
 | 
					//	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//Create workspace
 | 
						//Create workspace
 | 
				
			||||||
	char *ws_name = NULL;
 | 
						char *ws_name = NULL;
 | 
				
			||||||
| 
						 | 
					@ -79,7 +76,10 @@ swayc_t *new_output(wlc_handle handle) {
 | 
				
			||||||
	if (!ws_name) {
 | 
						if (!ws_name) {
 | 
				
			||||||
		ws_name = workspace_next_name();
 | 
							ws_name = workspace_next_name();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	new_workspace(output, ws_name);
 | 
						//create and initilize default workspace
 | 
				
			||||||
 | 
						swayc_t *ws = new_workspace(output, ws_name);
 | 
				
			||||||
 | 
						ws->is_focused = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(ws_name);
 | 
						free(ws_name);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	return output;
 | 
						return output;
 | 
				
			||||||
| 
						 | 
					@ -141,12 +141,13 @@ 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) {
 | 
				
			||||||
	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 %u:%s to container %p %d",
 | 
						sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d",
 | 
				
			||||||
		(unsigned int)handle, title, sibling, sibling?sibling->type:0);
 | 
							handle, title, sibling, sibling ? sibling->type : 0);
 | 
				
			||||||
	//Setup values
 | 
						//Setup values
 | 
				
			||||||
	view->handle = handle;
 | 
						view->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->desired_width = -1;
 | 
						view->desired_width = -1;
 | 
				
			||||||
	view->desired_height = -1;
 | 
						view->desired_height = -1;
 | 
				
			||||||
| 
						 | 
					@ -168,8 +169,8 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
 | 
				
			||||||
swayc_t *new_floating_view(wlc_handle handle) {
 | 
					swayc_t *new_floating_view(wlc_handle handle) {
 | 
				
			||||||
	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 %u:%s as a floating view",
 | 
						sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view",
 | 
				
			||||||
		(unsigned int)handle, title);
 | 
							handle, wlc_view_get_type(handle), title);
 | 
				
			||||||
	//Setup values
 | 
						//Setup values
 | 
				
			||||||
	view->handle = handle;
 | 
						view->handle = handle;
 | 
				
			||||||
	view->name = title ? strdup(title) : NULL;
 | 
						view->name = title ? strdup(title) : NULL;
 | 
				
			||||||
| 
						 | 
					@ -197,6 +198,7 @@ swayc_t *new_floating_view(wlc_handle handle) {
 | 
				
			||||||
	return view;
 | 
						return view;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Destroy container */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *destroy_output(swayc_t *output) {
 | 
					swayc_t *destroy_output(swayc_t *output) {
 | 
				
			||||||
	if (output->children->length == 0) {
 | 
						if (output->children->length == 0) {
 | 
				
			||||||
| 
						 | 
					@ -300,3 +302,5 @@ void set_view_visibility(swayc_t *view, void *data) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	view->visible = (*p == 2);
 | 
						view->visible = (*p == 2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										186
									
								
								sway/focus.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								sway/focus.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,186 @@
 | 
				
			||||||
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "focus.h"
 | 
				
			||||||
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "workspace.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool locked_container_focus = false;
 | 
				
			||||||
 | 
					bool locked_view_focus = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//switches parent focus to c. will switch it accordingly
 | 
				
			||||||
 | 
					//TODO, everything needs a handle, so we can set front/back position properly
 | 
				
			||||||
 | 
					static void update_focus(swayc_t *c) {
 | 
				
			||||||
 | 
						//Handle if focus switches
 | 
				
			||||||
 | 
						swayc_t *parent = c->parent;
 | 
				
			||||||
 | 
						if (parent->focused != c) {
 | 
				
			||||||
 | 
							switch (c->type) {
 | 
				
			||||||
 | 
							case C_ROOT: return;
 | 
				
			||||||
 | 
							case C_OUTPUT:
 | 
				
			||||||
 | 
								wlc_output_focus(c->parent->handle);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							//switching workspaces
 | 
				
			||||||
 | 
							case C_WORKSPACE:
 | 
				
			||||||
 | 
								if (parent->focused) {
 | 
				
			||||||
 | 
									swayc_t *ws = parent->focused;
 | 
				
			||||||
 | 
									//hide visibility of old workspace
 | 
				
			||||||
 | 
									uint32_t mask = 1;
 | 
				
			||||||
 | 
									container_map(ws, set_view_visibility, &mask);
 | 
				
			||||||
 | 
									//set visibility of new workspace
 | 
				
			||||||
 | 
									mask = 2;
 | 
				
			||||||
 | 
									container_map(c, set_view_visibility, &mask);
 | 
				
			||||||
 | 
									wlc_output_set_mask(parent->handle, 2);
 | 
				
			||||||
 | 
									destroy_workspace(ws);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								active_workspace = c;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case C_VIEW:
 | 
				
			||||||
 | 
							case C_CONTAINER:
 | 
				
			||||||
 | 
								//TODO whatever to do when container changes
 | 
				
			||||||
 | 
								//for example, stacked and tabbing change whatever.
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c->parent->focused = c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool move_focus(enum movement_direction direction) {
 | 
				
			||||||
 | 
						if (locked_container_focus) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						swayc_t *current = get_focused_container(&root_container);
 | 
				
			||||||
 | 
						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 {
 | 
				
			||||||
 | 
								sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld",
 | 
				
			||||||
 | 
									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;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *get_focused_container(swayc_t *parent) {
 | 
				
			||||||
 | 
						while (parent && !parent->is_focused) {
 | 
				
			||||||
 | 
							parent = parent->focused;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return parent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void set_focused_container(swayc_t *c) {
 | 
				
			||||||
 | 
						if (locked_container_focus || !c) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle);
 | 
				
			||||||
 | 
						if (c->type != C_ROOT && c->type != C_OUTPUT) {
 | 
				
			||||||
 | 
							c->is_focused = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						swayc_t *prev_view = get_focused_view(&root_container);
 | 
				
			||||||
 | 
						swayc_t *p = c;
 | 
				
			||||||
 | 
						while (p != &root_container) {
 | 
				
			||||||
 | 
							update_focus(p);
 | 
				
			||||||
 | 
							p = p->parent;
 | 
				
			||||||
 | 
							p->is_focused = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!locked_view_focus) {
 | 
				
			||||||
 | 
							p = get_focused_view(c);
 | 
				
			||||||
 | 
							//Set focus to p
 | 
				
			||||||
 | 
							if (p && p != prev_view && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) {
 | 
				
			||||||
 | 
								if (prev_view) {
 | 
				
			||||||
 | 
									wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								wlc_view_focus(p->handle);
 | 
				
			||||||
 | 
								wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void set_focused_container_for(swayc_t *a, swayc_t *c) {
 | 
				
			||||||
 | 
						if (locked_container_focus || !c) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						swayc_t *find = c;
 | 
				
			||||||
 | 
						//Ensure that a is an ancestor of c
 | 
				
			||||||
 | 
						while (find != a && (find = find->parent)) {
 | 
				
			||||||
 | 
							if (find == &root_container) {
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld",
 | 
				
			||||||
 | 
							a, a->handle, c, c->handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->is_focused = true;
 | 
				
			||||||
 | 
						swayc_t *p = c;
 | 
				
			||||||
 | 
						while (p != a) {
 | 
				
			||||||
 | 
							update_focus(p);
 | 
				
			||||||
 | 
							p = p->parent;
 | 
				
			||||||
 | 
							p->is_focused = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!locked_view_focus) {
 | 
				
			||||||
 | 
							p = get_focused_view(c);
 | 
				
			||||||
 | 
							//Set focus to p
 | 
				
			||||||
 | 
							if (p) {
 | 
				
			||||||
 | 
								wlc_view_focus(p->handle);
 | 
				
			||||||
 | 
								wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					swayc_t *get_focused_view(swayc_t *parent) {
 | 
				
			||||||
 | 
						while (parent && parent->type != C_VIEW) {
 | 
				
			||||||
 | 
							parent = parent->focused;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return parent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										197
									
								
								sway/handlers.c
									
										
									
									
									
								
							
							
						
						
									
										197
									
								
								sway/handlers.c
									
										
									
									
									
								
							| 
						 | 
					@ -3,18 +3,18 @@
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <wlc/wlc.h>
 | 
					#include <wlc/wlc.h>
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
#include "layout.h"
 | 
					
 | 
				
			||||||
 | 
					#include "handlers.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					#include "layout.h"
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#include "commands.h"
 | 
					#include "commands.h"
 | 
				
			||||||
#include "handlers.h"
 | 
					 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
#include "workspace.h"
 | 
					#include "workspace.h"
 | 
				
			||||||
#include "container.h"
 | 
					#include "container.h"
 | 
				
			||||||
 | 
					#include "focus.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct wlc_origin mouse_origin;
 | 
					static struct wlc_origin mouse_origin;
 | 
				
			||||||
//Keyboard input is being overrided by window (dmenu)
 | 
					 | 
				
			||||||
static bool override_redirect = 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;
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ static bool pointer_test(swayc_t *view, void *_origin) {
 | 
				
			||||||
	while (parent->type != C_OUTPUT) {
 | 
						while (parent->type != C_OUTPUT) {
 | 
				
			||||||
		parent = parent->parent;
 | 
							parent = parent->parent;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (view->type == C_VIEW && 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) {
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
| 
						 | 
					@ -31,19 +31,49 @@ static bool pointer_test(swayc_t *view, void *_origin) {
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *focus_pointer(void) {
 | 
					swayc_t *container_under_pointer(void) {
 | 
				
			||||||
	swayc_t *focused = get_focused_container(&root_container);
 | 
						//root.output->workspace
 | 
				
			||||||
	if (!(wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) {
 | 
						swayc_t *lookup = root_container.focused->focused;
 | 
				
			||||||
		swayc_t *pointer = find_container(&root_container, pointer_test, &mouse_origin);
 | 
						//Case of empty workspace
 | 
				
			||||||
		if (pointer && focused != pointer) {
 | 
						if (lookup->children == 0) {
 | 
				
			||||||
			unfocus_all(&root_container);
 | 
							return NULL;
 | 
				
			||||||
			focus_view(pointer);
 | 
					 | 
				
			||||||
		} else if (!focused) {
 | 
					 | 
				
			||||||
			focus_view(active_workspace);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		focused = pointer;
 | 
						while (lookup->type != C_VIEW) {
 | 
				
			||||||
 | 
							int i;
 | 
				
			||||||
 | 
							int len;
 | 
				
			||||||
 | 
							//if tabbed/stacked go directly to focused container, otherwise search
 | 
				
			||||||
 | 
							//children
 | 
				
			||||||
 | 
							if (lookup->layout == L_TABBED || lookup->layout == L_STACKED) {
 | 
				
			||||||
 | 
								lookup = lookup->focused;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	return focused;
 | 
							//if workspace, search floating
 | 
				
			||||||
 | 
							if (lookup->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
								len = lookup->floating->length;
 | 
				
			||||||
 | 
								for (i = 0; i < len; ++i) {
 | 
				
			||||||
 | 
									if (pointer_test(lookup->floating->items[i], &mouse_origin)) {
 | 
				
			||||||
 | 
										lookup = lookup->floating->items[i];
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (i < len) {
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//search children
 | 
				
			||||||
 | 
							len = lookup->children->length;
 | 
				
			||||||
 | 
							for (i = 0; i < len; ++i) {
 | 
				
			||||||
 | 
								if (pointer_test(lookup->children->items[i], &mouse_origin)) {
 | 
				
			||||||
 | 
									lookup = lookup->children->items[i];
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//when border and titles are done, this could happen
 | 
				
			||||||
 | 
							if (i == len) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return lookup;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_output_created(wlc_handle output) {
 | 
					static bool handle_output_created(wlc_handle output) {
 | 
				
			||||||
| 
						 | 
					@ -81,97 +111,88 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_output_focused(wlc_handle output, bool focus) {
 | 
					static void handle_output_focused(wlc_handle output, bool focus) {
 | 
				
			||||||
	swayc_t *c = get_swayc_for_handle(output, &root_container);
 | 
						swayc_t *c = get_swayc_for_handle(output, &root_container);
 | 
				
			||||||
	if (!c) return;
 | 
						//if for some reason this output doesnt exist, create it.
 | 
				
			||||||
 | 
						if (!c) {
 | 
				
			||||||
 | 
							handle_output_created(output);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (focus) {
 | 
						if (focus) {
 | 
				
			||||||
		unfocus_all(&root_container);
 | 
							set_focused_container(c);
 | 
				
			||||||
		focus_view(c);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_view_created(wlc_handle handle) {
 | 
					static bool handle_view_created(wlc_handle handle) {
 | 
				
			||||||
	swayc_t *focused = get_focused_container(&root_container);
 | 
						swayc_t *focused = get_focused_container(&root_container);
 | 
				
			||||||
	uint32_t type = wlc_view_get_type(handle);
 | 
						swayc_t *newview = NULL;
 | 
				
			||||||
	// If override_redirect/unmanaged/popup/modal/splach
 | 
						switch (wlc_view_get_type(handle)) {
 | 
				
			||||||
	if (type) {
 | 
						//regular view created regularly
 | 
				
			||||||
		sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type);
 | 
						case 0:
 | 
				
			||||||
		wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
 | 
							newview = new_view(focused, handle);
 | 
				
			||||||
		if (type & WLC_BIT_UNMANAGED) {
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// For things like Dmenu
 | 
					 | 
				
			||||||
		if (type & WLC_BIT_OVERRIDE_REDIRECT) {
 | 
					 | 
				
			||||||
			override_redirect = true;
 | 
					 | 
				
			||||||
			wlc_view_focus(handle);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Float popups
 | 
					 | 
				
			||||||
		if (type & WLC_BIT_POPUP) {
 | 
					 | 
				
			||||||
			swayc_t *view = new_floating_view(handle);
 | 
					 | 
				
			||||||
			wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, false);
 | 
					 | 
				
			||||||
			focus_view(view);
 | 
					 | 
				
			||||||
			arrange_windows(active_workspace, -1, -1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		swayc_t *view = new_view(focused, handle);
 | 
					 | 
				
			||||||
		//Set maximize flag for windows.
 | 
					 | 
				
			||||||
		//TODO: floating windows have this unset
 | 
					 | 
				
			||||||
		wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
 | 
							wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
 | 
				
			||||||
		unfocus_all(&root_container);
 | 
							break;
 | 
				
			||||||
		focus_view(view);
 | 
						//takes keyboard focus
 | 
				
			||||||
		arrange_windows(view->parent, -1, -1);
 | 
						case WLC_BIT_OVERRIDE_REDIRECT:
 | 
				
			||||||
 | 
							sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle);
 | 
				
			||||||
 | 
							locked_view_focus = true;
 | 
				
			||||||
 | 
							wlc_view_focus(handle);
 | 
				
			||||||
 | 
							wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
 | 
				
			||||||
 | 
							wlc_view_bring_to_front(handle);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						//Takes container focus
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
							locked_container_focus = true;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						//set modals as floating containers
 | 
				
			||||||
 | 
						case WLC_BIT_POPUP:
 | 
				
			||||||
 | 
						case WLC_BIT_MODAL:
 | 
				
			||||||
 | 
							wlc_view_bring_to_front(handle);
 | 
				
			||||||
 | 
							newview = new_floating_view(handle);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
 | 
						if (newview) {
 | 
				
			||||||
		unfocus_all(&root_container);
 | 
							set_focused_container(newview);
 | 
				
			||||||
		focus_view(focused);
 | 
							arrange_windows(newview->parent, -1, -1);
 | 
				
			||||||
		arrange_windows(focused, -1, -1);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_view_destroyed(wlc_handle handle) {
 | 
					static void handle_view_destroyed(wlc_handle handle) {
 | 
				
			||||||
	sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle);
 | 
						sway_log(L_DEBUG, "Destroying window %lu", handle);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Properly handle unmanaged views
 | 
					 | 
				
			||||||
	uint32_t type = wlc_view_get_type(handle);
 | 
					 | 
				
			||||||
	if (type) {
 | 
					 | 
				
			||||||
		wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type);
 | 
					 | 
				
			||||||
		if (type & WLC_BIT_UNMANAGED) {
 | 
					 | 
				
			||||||
			// We need to call focus_view() on focus_pointer because unmanaged windows
 | 
					 | 
				
			||||||
			// do not alter the focus structure of the container tree. This makes focus_pointer()
 | 
					 | 
				
			||||||
			// think that it doesn't need to do anything, so we manually focus the result.
 | 
					 | 
				
			||||||
			focus_view(focus_pointer());
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (type & WLC_BIT_OVERRIDE_REDIRECT) {
 | 
					 | 
				
			||||||
			override_redirect = false;
 | 
					 | 
				
			||||||
			focus_view(focus_pointer());
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// WLC_BIT_POPUP doesn't need to be dealt with since it's
 | 
					 | 
				
			||||||
		// treated as a floating view.
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	swayc_t *view = get_swayc_for_handle(handle, &root_container);
 | 
						swayc_t *view = get_swayc_for_handle(handle, &root_container);
 | 
				
			||||||
	swayc_t *parent;
 | 
					 | 
				
			||||||
	swayc_t *focused = get_focused_container(&root_container);
 | 
						swayc_t *focused = get_focused_container(&root_container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (wlc_view_get_type(handle)) {
 | 
				
			||||||
 | 
						//regular view created regularly
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
						case WLC_BIT_MODAL:
 | 
				
			||||||
 | 
						case WLC_BIT_POPUP:
 | 
				
			||||||
		if (view) {
 | 
							if (view) {
 | 
				
			||||||
		parent = destroy_view(view);
 | 
								arrange_windows(destroy_view(view), -1, -1);
 | 
				
			||||||
		arrange_windows(parent, -1, -1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
			if (!focused || focused == view) {
 | 
								if (!focused || focused == view) {
 | 
				
			||||||
		focus_pointer();
 | 
									set_focused_container(container_under_pointer());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						//takes keyboard focus
 | 
				
			||||||
 | 
						case WLC_BIT_OVERRIDE_REDIRECT:
 | 
				
			||||||
 | 
							locked_view_focus = false;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						//Takes container focus
 | 
				
			||||||
 | 
						case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
 | 
				
			||||||
 | 
							locked_container_focus = false;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						set_focused_container(get_focused_view(&root_container));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_view_focus(wlc_handle view, bool focus) {
 | 
					static void handle_view_focus(wlc_handle view, bool focus) {
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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",
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
| 
						 | 
					@ -191,12 +212,12 @@ 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;
 | 
				
			||||||
	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);
 | 
				
			||||||
			swayc_t *c = get_swayc_for_handle(view, &root_container);
 | 
							c = get_swayc_for_handle(view, &root_container);
 | 
				
			||||||
		sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle);
 | 
							sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle);
 | 
				
			||||||
		if (c) {
 | 
							if (c) {
 | 
				
			||||||
			arrange_windows(c->parent, -1, -1);
 | 
								arrange_windows(c->parent, -1, -1);
 | 
				
			||||||
| 
						 | 
					@ -208,11 +229,10 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s
 | 
				
			||||||
					ws = ws->parent;
 | 
										ws = ws->parent;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				//Set ws focus to c
 | 
									//Set ws focus to c
 | 
				
			||||||
					focus_view_for(ws, c);
 | 
									set_focused_container_for(ws, c);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case WLC_BIT_MAXIMIZED:
 | 
						case WLC_BIT_MAXIMIZED:
 | 
				
			||||||
	case WLC_BIT_RESIZING:
 | 
						case WLC_BIT_RESIZING:
 | 
				
			||||||
	case WLC_BIT_MOVING:
 | 
						case WLC_BIT_MOVING:
 | 
				
			||||||
| 
						 | 
					@ -226,7 +246,7 @@ 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
 | 
					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) {
 | 
							*modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) {
 | 
				
			||||||
	enum { QSIZE = 32 };
 | 
						enum { QSIZE = 32 };
 | 
				
			||||||
	if (override_redirect) {
 | 
						if (locked_view_focus) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	static uint8_t  head = 0;
 | 
						static uint8_t  head = 0;
 | 
				
			||||||
| 
						 | 
					@ -295,7 +315,7 @@ static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct w
 | 
				
			||||||
	static wlc_handle prev_view = 0;
 | 
						static wlc_handle prev_view = 0;
 | 
				
			||||||
	mouse_origin = *origin;
 | 
						mouse_origin = *origin;
 | 
				
			||||||
	if (config->focus_follows_mouse && prev_view != view) {
 | 
						if (config->focus_follows_mouse && prev_view != view) {
 | 
				
			||||||
		focus_pointer();
 | 
							set_focused_container(container_under_pointer());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prev_view = view;
 | 
						prev_view = view;
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
| 
						 | 
					@ -305,7 +325,8 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
 | 
				
			||||||
		uint32_t button, enum wlc_button_state state) {
 | 
							uint32_t button, enum wlc_button_state state) {
 | 
				
			||||||
	swayc_t *focused = get_focused_container(&root_container);
 | 
						swayc_t *focused = get_focused_container(&root_container);
 | 
				
			||||||
	if (state == WLC_BUTTON_STATE_PRESSED) {
 | 
						if (state == WLC_BUTTON_STATE_PRESSED) {
 | 
				
			||||||
		swayc_t *pointer = focus_pointer();
 | 
							swayc_t *pointer = container_under_pointer();
 | 
				
			||||||
 | 
							set_focused_container(pointer);
 | 
				
			||||||
		return (pointer && pointer != focused);
 | 
							return (pointer && pointer != focused);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,9 +31,6 @@ 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;
 | 
				
			||||||
	if (parent->focused == NULL) {
 | 
					 | 
				
			||||||
		parent->focused = child;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) {
 | 
					swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) {
 | 
				
			||||||
| 
						 | 
					@ -206,7 +203,7 @@ void arrange_windows(swayc_t *container, int width, int height) {
 | 
				
			||||||
	// Arrage floating layouts for workspaces last
 | 
						// Arrage floating layouts for workspaces last
 | 
				
			||||||
	if (container->type == C_WORKSPACE) {
 | 
						if (container->type == C_WORKSPACE) {
 | 
				
			||||||
		for (i = 0; i < container->floating->length; ++i) {
 | 
							for (i = 0; i < container->floating->length; ++i) {
 | 
				
			||||||
			swayc_t *view = ((swayc_t *)container->floating->items[i]);
 | 
								swayc_t *view = container->floating->items[i];
 | 
				
			||||||
			// Set the geometry
 | 
								// Set the geometry
 | 
				
			||||||
			struct wlc_geometry geometry = {
 | 
								struct wlc_geometry geometry = {
 | 
				
			||||||
				.origin = {
 | 
									.origin = {
 | 
				
			||||||
| 
						 | 
					@ -262,64 +259,3 @@ swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) {
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *get_focused_container(swayc_t *parent) {
 | 
					 | 
				
			||||||
	if (parent->focused == NULL) {
 | 
					 | 
				
			||||||
		return parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return get_focused_container(parent->focused);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void unfocus_all(swayc_t *container) {
 | 
					 | 
				
			||||||
	if (container->children == NULL) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	for (i = 0; i < container->children->length; ++i) {
 | 
					 | 
				
			||||||
		swayc_t *view = container->children->items[i];
 | 
					 | 
				
			||||||
		if (view->type == C_VIEW) {
 | 
					 | 
				
			||||||
			wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, false);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			unfocus_all(view);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void focus_view(swayc_t *view) {
 | 
					 | 
				
			||||||
	if (!view) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Setting focus for %p:%ld", view, view->handle);
 | 
					 | 
				
			||||||
	swayc_t *c = view;
 | 
					 | 
				
			||||||
	//Set focus from root to view
 | 
					 | 
				
			||||||
	while (c != &root_container) {
 | 
					 | 
				
			||||||
		c->parent->focused = c;
 | 
					 | 
				
			||||||
		c = c->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	//Set output
 | 
					 | 
				
			||||||
	wlc_output_focus(c->focused->handle);
 | 
					 | 
				
			||||||
	//get focus for views focused window
 | 
					 | 
				
			||||||
	while (view && view->type != C_VIEW) {
 | 
					 | 
				
			||||||
		view = view->focused;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (view) {
 | 
					 | 
				
			||||||
		wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, true);
 | 
					 | 
				
			||||||
		wlc_view_focus(view->handle);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void focus_view_for(swayc_t *top, swayc_t *view) {
 | 
					 | 
				
			||||||
	swayc_t *find = view;
 | 
					 | 
				
			||||||
	//Make sure top is a ancestor of view
 | 
					 | 
				
			||||||
	while (find != top) {
 | 
					 | 
				
			||||||
		if (find == &root_container) {
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		find = find->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	//Set focus for top to go to view
 | 
					 | 
				
			||||||
	while (view != top) {
 | 
					 | 
				
			||||||
		view->parent->focused = view;
 | 
					 | 
				
			||||||
		view = view->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@
 | 
				
			||||||
int colored = 1;
 | 
					int colored = 1;
 | 
				
			||||||
int v = 0;
 | 
					int v = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *verbosity_colors[] = {
 | 
					static const char *verbosity_colors[] = {
 | 
				
			||||||
	"", // L_SILENT
 | 
						"", // L_SILENT
 | 
				
			||||||
	"\x1B[1;31m", // L_ERROR
 | 
						"\x1B[1;31m", // L_ERROR
 | 
				
			||||||
	"\x1B[1;34m", // L_INFO
 | 
						"\x1B[1;34m", // L_INFO
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,70 +0,0 @@
 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
#include "list.h"
 | 
					 | 
				
			||||||
#include "log.h"
 | 
					 | 
				
			||||||
#include "layout.h"
 | 
					 | 
				
			||||||
#include "movement.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool move_focus(enum movement_direction direction) {
 | 
					 | 
				
			||||||
	swayc_t *current = get_focused_container(&root_container);
 | 
					 | 
				
			||||||
	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 {
 | 
					 | 
				
			||||||
			sway_log(L_DEBUG, "Moving focus away from %p to %p", current, parent);
 | 
					 | 
				
			||||||
			unfocus_all(parent->parent);
 | 
					 | 
				
			||||||
			focus_view(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 {
 | 
					 | 
				
			||||||
				unfocus_all(&root_container);
 | 
					 | 
				
			||||||
				focus_view(parent->children->items[desired]);
 | 
					 | 
				
			||||||
				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;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include "handlers.h"
 | 
					#include "handlers.h"
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
 | 
					#include "focus.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *active_workspace = NULL;
 | 
					swayc_t *active_workspace = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,59 +174,28 @@ void workspace_prev() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void workspace_switch(swayc_t *workspace) {
 | 
					void workspace_switch(swayc_t *workspace) {
 | 
				
			||||||
	swayc_t *ws_output = workspace->parent;
 | 
						set_focused_container(workspace);
 | 
				
			||||||
	while (ws_output->type != C_OUTPUT) {
 | 
					 | 
				
			||||||
		ws_output = ws_output->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// The current workspace of the output our target workspace is in
 | 
					 | 
				
			||||||
	swayc_t *focused_workspace = ws_output->focused;
 | 
					 | 
				
			||||||
	if (workspace != focused_workspace && focused_workspace) {
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG, "workspace: changing from '%s' to '%s'", focused_workspace->name, workspace->name);
 | 
					 | 
				
			||||||
		uint32_t mask = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// set all c_views in the old workspace to the invisible mask if the workspace
 | 
					 | 
				
			||||||
		// is in the same output & c_views in the new workspace to the visible mask
 | 
					 | 
				
			||||||
		container_map(focused_workspace, set_view_visibility, &mask);
 | 
					 | 
				
			||||||
		mask = 2;
 | 
					 | 
				
			||||||
		container_map(workspace, set_view_visibility, &mask);
 | 
					 | 
				
			||||||
		wlc_output_set_mask(ws_output->handle, 2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		destroy_workspace(focused_workspace);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	unfocus_all(&root_container);
 | 
					 | 
				
			||||||
	focus_view(workspace);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// focus the output this workspace is on
 | 
					 | 
				
			||||||
	swayc_t *output = workspace->parent;
 | 
					 | 
				
			||||||
	sway_log(L_DEBUG, "Switching focus to output %p (%d)", output, output->type);
 | 
					 | 
				
			||||||
	while (output && output->type != C_OUTPUT) {
 | 
					 | 
				
			||||||
		output = output->parent;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (output) {
 | 
					 | 
				
			||||||
		sway_log(L_DEBUG, "Switching focus to output %p (%d)", output, output->type);
 | 
					 | 
				
			||||||
		wlc_output_focus(output->handle);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	active_workspace = workspace;
 | 
						active_workspace = workspace;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XXX:DEBUG:XXX */
 | 
					/* XXX:DEBUG:XXX */
 | 
				
			||||||
static void container_log(const swayc_t *c) {
 | 
					static void container_log(const swayc_t *c) {
 | 
				
			||||||
	fprintf(stderr, "focus:%c|",
 | 
						fprintf(stderr, "focus:%c|",
 | 
				
			||||||
		c == get_focused_container(&root_container) ? 'F' : //Focused
 | 
							c->is_focused ? 'F' : //Focused
 | 
				
			||||||
		c == active_workspace ? 'W' : //active workspace
 | 
							c == active_workspace ? 'W' : //active workspace
 | 
				
			||||||
		c == &root_container  ? 'R' : //root
 | 
							c == &root_container  ? 'R' : //root
 | 
				
			||||||
		'X');//not any others
 | 
							'X');//not any others
 | 
				
			||||||
	fprintf(stderr,"(%p)",c);
 | 
						fprintf(stderr,"(%p)",c);
 | 
				
			||||||
	fprintf(stderr,"(p:%p)",c->parent);
 | 
						fprintf(stderr,"(p:%p)",c->parent);
 | 
				
			||||||
	fprintf(stderr,"(f:%p)",c->focused);
 | 
						fprintf(stderr,"(f:%p)",c->focused);
 | 
				
			||||||
 | 
						fprintf(stderr,"(h:%ld)",c->handle);
 | 
				
			||||||
	fprintf(stderr,"Type:");
 | 
						fprintf(stderr,"Type:");
 | 
				
			||||||
	fprintf(stderr,
 | 
						fprintf(stderr,
 | 
				
			||||||
		c->type == C_ROOT   ? "Root|" :
 | 
							c->type == C_ROOT   ? "Root|" :
 | 
				
			||||||
		c->type == C_OUTPUT ? "Output|" :
 | 
							c->type == C_OUTPUT ? "Output|" :
 | 
				
			||||||
		c->type == C_WORKSPACE ? "Workspace|" :
 | 
							c->type == C_WORKSPACE ? "Workspace|" :
 | 
				
			||||||
		c->type == C_CONTAINER ? "Container|" :
 | 
							c->type == C_CONTAINER ? "Container|" :
 | 
				
			||||||
		c->type == C_VIEW	  ? "View|" :
 | 
							c->type == C_VIEW   ? "View|" : "Unknown|");
 | 
				
			||||||
								 "Unknown|");
 | 
					 | 
				
			||||||
	fprintf(stderr,"layout:");
 | 
						fprintf(stderr,"layout:");
 | 
				
			||||||
	fprintf(stderr,
 | 
						fprintf(stderr,
 | 
				
			||||||
		c->layout == L_NONE ? "NONE|" :
 | 
							c->layout == L_NONE ? "NONE|" :
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue