diff --git a/client/src/message.c b/client/src/message.c new file mode 100644 index 00000000..aa06e925 --- /dev/null +++ b/client/src/message.c @@ -0,0 +1,143 @@ +/** + * Looking Glass + * Copyright © 2017-2025 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "message.h" +#include "core.h" +#include "common/debug.h" +#include "common/ll.h" +#include "common/time.h" + +#include +#include +#include + +typedef struct MsgEvent +{ + uint64_t timestamp; + LGMsg msg; +} +MsgEvent; + +struct MsgState +{ + struct ll * list; + struct + { + unsigned width; + unsigned height; + } + lastWindowSize; +}; + +static struct MsgState this = {0}; + +bool lgMessage_init(void) +{ + this.list = ll_new(); + if (!this.list) + { + DEBUG_ERROR("Failed to create the message list"); + return false; + } + + return true; +} + +void lgMessage_deinit(void) +{ + if (this.list) + { + ll_free(this.list); + this.list = NULL; + } +} + +void lgMessage_post(const LGMsg * msg) +{ + MsgEvent * event = (MsgEvent *)malloc(sizeof(*event)); + if (!event) + { + DEBUG_ERROR("Out of memory"); + return; + } + + event->timestamp = microtime(); + memcpy(&event->msg, msg, sizeof(event->msg)); + if (!ll_push(this.list, event)) + { + DEBUG_ERROR("Failed to post a message to the list"); + free(event); + } +} + +void lgMessage_process(void) +{ + MsgEvent * event; + MsgEvent * windowSize = NULL; + + while(ll_shift(this.list, (void **)&event)) + { + switch(event->msg.type) + { + case LG_MSG_WINDOWSIZE: + { + // retain the last/latest windowsize event + if (windowSize) + free(windowSize); + windowSize = event; + continue; + } + + case LG_MSG_VIDEO: + default: + break; + } + + free(event); + } + + // if there was a windowSize event, then process it + if (windowSize) + { + const uint64_t time = microtime(); + if (time - windowSize->timestamp < 500000) + { + // requeue the event for later + if (!ll_push(this.list, event)) + { + DEBUG_ERROR("Failed to re-queue the windowSize event"); + free(windowSize); + } + } + else + { + if (event->msg.windowSize.width != this.lastWindowSize.width || + event->msg.windowSize.height != this.lastWindowSize.height) + { + this.lastWindowSize.width = event->msg.windowSize.width; + this.lastWindowSize.height = event->msg.windowSize.height; + core_onWindowSizeChanged( + event->msg.windowSize.width, + event->msg.windowSize.height); + } + free(windowSize); + } + } +} diff --git a/client/src/message.h b/client/src/message.h new file mode 100644 index 00000000..d390ed02 --- /dev/null +++ b/client/src/message.h @@ -0,0 +1,66 @@ +/** + * Looking Glass + * Copyright © 2017-2025 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _H_LG_MSG_ +#define _H_LG_MSG_ + +#include + +typedef enum LGMsgType +{ + /* The LG client window size changed + * Note: + * This message is debounced to avoid flooding the guest with resize events + */ + LG_MSG_WINDOWSIZE +} +LGMsgType; + +typedef struct LGMsg +{ + LGMsgType type; + union + { + //LG_MSG_WINDOWSIZE + struct + { + unsigned width; + unsigned height; + } + windowSize; + + //LG_MSG_VIDEO + struct + { + bool enabled; + } + video; + }; +} +LGMsg; + +bool lgMessage_init(void); +void lgMessage_deinit(void); + +void lgMessage_process(void); + +void lgMessage_post(const LGMsg * msg); + +#endif diff --git a/common/include/common/ll.h b/common/include/common/ll.h index 652b2658..55985861 100644 --- a/common/include/common/ll.h +++ b/common/include/common/ll.h @@ -42,7 +42,7 @@ struct ll struct ll * ll_new(void); void ll_free (struct ll * list); -void ll_push (struct ll * list, void * data); +bool ll_push (struct ll * list, void * data); bool ll_shift (struct ll * list, void ** data); bool ll_shift_nl (struct ll * list, void ** data); bool ll_peek_head (struct ll * list, void ** data); diff --git a/common/src/ll.c b/common/src/ll.c index 267d2738..72a319f7 100644 --- a/common/src/ll.c +++ b/common/src/ll.c @@ -48,13 +48,13 @@ void ll_free(struct ll * list) free(list); } -void ll_push(struct ll * list, void * data) +bool ll_push(struct ll * list, void * data) { struct ll_item * item = malloc(sizeof(*item)); if (!item) { DEBUG_ERROR("out of memory"); - return; + return false; } item->data = data; @@ -69,7 +69,7 @@ void ll_push(struct ll * list, void * data) list->head = item; list->tail = item; LG_UNLOCK(list->lock); - return; + return true; } item->prev = list->tail; @@ -78,6 +78,7 @@ void ll_push(struct ll * list, void * data) list->tail = item; LG_UNLOCK(list->lock); + return true; } bool ll_shift(struct ll * list, void ** data)