mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Allow views to skip configures
To do this properly, the transaction queue will only be processed if it can be completely processed.
This commit is contained in:
		
							parent
							
								
									e6829c5991
								
							
						
					
					
						commit
						9652529cc1
					
				
					 5 changed files with 42 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -62,6 +62,13 @@ void list_cat(list_t *list, list_t *source) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void list_empty(list_t *list) {
 | 
			
		||||
	list->capacity = 10;
 | 
			
		||||
	list->length = 0;
 | 
			
		||||
	free(list->items);
 | 
			
		||||
	list->items = malloc(sizeof(void*) * list->capacity);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void list_qsort(list_t *list, int compare(const void *left, const void *right)) {
 | 
			
		||||
	qsort(list->items, list->length, sizeof(void *), compare);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ void list_add(list_t *list, void *item);
 | 
			
		|||
void list_insert(list_t *list, int index, void *item);
 | 
			
		||||
void list_del(list_t *list, int index);
 | 
			
		||||
void list_cat(list_t *list, list_t *source);
 | 
			
		||||
void list_empty(list_t *list);
 | 
			
		||||
// See qsort. Remember to use *_qsort functions as compare functions,
 | 
			
		||||
// because they dereference the left and right arguments first!
 | 
			
		||||
void list_qsort(list_t *list, int compare(const void *left, const void *right));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ struct sway_server {
 | 
			
		|||
 | 
			
		||||
	bool debug_txn_timings;
 | 
			
		||||
 | 
			
		||||
	struct sway_transaction *head_transaction; // singly linked list
 | 
			
		||||
	list_t *transactions;
 | 
			
		||||
 | 
			
		||||
	// When a view is being destroyed and is waiting for a transaction to
 | 
			
		||||
	// complete it will be stored here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,6 @@ struct sway_transaction {
 | 
			
		|||
	list_t *instructions;   // struct sway_transaction_instruction *
 | 
			
		||||
	size_t num_waiting;
 | 
			
		||||
	size_t num_configures;
 | 
			
		||||
	struct sway_transaction *next;
 | 
			
		||||
	struct timespec create_time;
 | 
			
		||||
	struct timespec commit_time;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -225,16 +224,24 @@ static void transaction_apply(struct sway_transaction *transaction) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * For simplicity, we only progress the queue if it can be completely flushed.
 | 
			
		||||
 */
 | 
			
		||||
static void transaction_progress_queue() {
 | 
			
		||||
	struct sway_transaction *transaction = server.head_transaction;
 | 
			
		||||
	struct sway_transaction *next = NULL;
 | 
			
		||||
	while (transaction && !transaction->num_waiting) {
 | 
			
		||||
		next = transaction->next;
 | 
			
		||||
	// We iterate this list in reverse because we're more likely to find a
 | 
			
		||||
	// waiting transactions at the end of the list.
 | 
			
		||||
	for (int i = server.transactions->length - 1; i >= 0; --i) {
 | 
			
		||||
		struct sway_transaction *transaction = server.transactions->items[i];
 | 
			
		||||
		if (transaction->num_waiting) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for (int i = 0; i < server.transactions->length; ++i) {
 | 
			
		||||
		struct sway_transaction *transaction = server.transactions->items[i];
 | 
			
		||||
		transaction_apply(transaction);
 | 
			
		||||
		transaction_destroy(transaction);
 | 
			
		||||
		transaction = next;
 | 
			
		||||
	}
 | 
			
		||||
	server.head_transaction = transaction;
 | 
			
		||||
	list_empty(server.transactions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int handle_timeout(void *data) {
 | 
			
		||||
| 
						 | 
				
			
			@ -295,18 +302,8 @@ void transaction_commit(struct sway_transaction *transaction) {
 | 
			
		|||
	if (server.debug_txn_timings) {
 | 
			
		||||
		clock_gettime(CLOCK_MONOTONIC, &transaction->commit_time);
 | 
			
		||||
	}
 | 
			
		||||
	if (server.head_transaction) {
 | 
			
		||||
		// There is another transaction in progress - we must add this one to
 | 
			
		||||
		// the queue so we complete after it.
 | 
			
		||||
		struct sway_transaction *tail = server.head_transaction;
 | 
			
		||||
		while (tail->next) {
 | 
			
		||||
			tail = tail->next;
 | 
			
		||||
		}
 | 
			
		||||
		tail->next = transaction;
 | 
			
		||||
	} else if (transaction->num_waiting) {
 | 
			
		||||
		// There are no other transactions, but we're not applying immediately
 | 
			
		||||
		// so we must jump in the queue so others will queue behind us.
 | 
			
		||||
		server.head_transaction = transaction;
 | 
			
		||||
	if (server.transactions->length || transaction->num_waiting) {
 | 
			
		||||
		list_add(server.transactions, transaction);
 | 
			
		||||
	} else {
 | 
			
		||||
		// There are no other transactions in progress, and this one has nothing
 | 
			
		||||
		// to wait for, so we can skip the queue.
 | 
			
		||||
| 
						 | 
				
			
			@ -359,12 +356,24 @@ static void set_instruction_ready(
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Mark all of the view's instructions as ready up to and including the
 | 
			
		||||
 * instruction at the given index. This allows the view to skip a configure.
 | 
			
		||||
 */
 | 
			
		||||
static void set_instructions_ready(struct sway_view *view, int index) {
 | 
			
		||||
	for (int i = 0; i <= index; ++i) {
 | 
			
		||||
		struct sway_transaction_instruction *instruction =
 | 
			
		||||
			view->swayc->instructions->items[i];
 | 
			
		||||
		set_instruction_ready(instruction);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void transaction_notify_view_ready(struct sway_view *view, uint32_t serial) {
 | 
			
		||||
	for (int i = 0; i < view->swayc->instructions->length; ++i) {
 | 
			
		||||
		struct sway_transaction_instruction *instruction =
 | 
			
		||||
			view->swayc->instructions->items[i];
 | 
			
		||||
		if (instruction->serial == serial && !instruction->ready) {
 | 
			
		||||
			set_instruction_ready(instruction);
 | 
			
		||||
			set_instructions_ready(view, i);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -377,7 +386,7 @@ void transaction_notify_view_ready_by_size(struct sway_view *view,
 | 
			
		|||
			view->swayc->instructions->items[i];
 | 
			
		||||
		if (!instruction->ready && instruction->state.view_width == width &&
 | 
			
		||||
				instruction->state.view_height == height) {
 | 
			
		||||
			set_instruction_ready(instruction);
 | 
			
		||||
			set_instructions_ready(view, i);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -119,6 +119,8 @@ bool server_init(struct sway_server *server) {
 | 
			
		|||
	}
 | 
			
		||||
	server->destroying_containers = create_list();
 | 
			
		||||
 | 
			
		||||
	server->transactions = create_list();
 | 
			
		||||
 | 
			
		||||
	input_manager = input_manager_create(server);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -127,6 +129,7 @@ void server_fini(struct sway_server *server) {
 | 
			
		|||
	// TODO: free sway-specific resources
 | 
			
		||||
	wl_display_destroy(server->wl_display);
 | 
			
		||||
	list_free(server->destroying_containers);
 | 
			
		||||
	list_free(server->transactions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void server_run(struct sway_server *server) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue