[PATCH 1/5] server: Added support for tracking registered device notifications
Micah N Gorrell
mgorrell at codeweavers.com
Fri May 17 19:35:24 CDT 2019
Signed-off-by: Micah N Gorrell <mgorrell at codeweavers.com>
---
server/protocol.def | 23 ++++++++++
server/user.h | 3 +-
server/window.c | 108 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/server/protocol.def b/server/protocol.def
index 21008d7a87..314a4477d0 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3684,6 +3684,29 @@ struct handle_info
@END
+/* Register a handle for device notifications */
+ at REQ(register_device_notification)
+ user_handle_t recipient; /* handle to a window or service that will receive device events */
+ at REPLY
+ user_handle_t handle; /* handle associated with the registration */
+ at END
+
+
+/* Unregister device notifications for a handle */
+ at REQ(unregister_device_notification)
+ user_handle_t notification; /* handle that was previously returned by register_device_notification */
+ at END
+
+
+/* Return a list of handles that have registered for device notifications */
+ at REQ(get_device_notifications)
+ at REPLY
+ int count; /* total count of registered handles */
+ VARARG(handles,user_handles); /* registered handles */
+ at END
+
+
+
/* Make the current process a system process */
@REQ(make_process_system)
@REPLY
diff --git a/server/user.h b/server/user.h
index eb1b7ce1e4..282cb63339 100644
--- a/server/user.h
+++ b/server/user.h
@@ -36,7 +36,8 @@ enum user_object
{
USER_WINDOW = 1,
USER_HOOK,
- USER_CLIENT /* arbitrary client handle */
+ USER_CLIENT, /* arbitrary client handle */
+ USER_DEVNOTIFY
};
#define DESKTOP_ATOM ((atom_t)32769)
diff --git a/server/window.c b/server/window.c
index c9b131cba5..5116fb12ff 100644
--- a/server/window.c
+++ b/server/window.c
@@ -129,6 +129,18 @@ static struct window *taskman_window;
#define WINPTR_TOPMOST ((struct window *)3L)
#define WINPTR_NOTOPMOST ((struct window *)4L)
+struct device_notification
+{
+ user_handle_t recipient; /* the window handle to send notifications to */
+ user_handle_t handle; /* full handle for this window */
+ struct list entry; /* entry in global notifications list */
+
+ /* FIXME: Add support for notification filters */
+};
+
+/* global list of handles that have registered for device notifications */
+static struct list device_notifications = LIST_INIT(device_notifications);
+
/* retrieve a pointer to a window from its handle */
static inline struct window *get_window( user_handle_t handle )
{
@@ -2880,3 +2892,99 @@ DECL_HANDLER(set_window_layered_info)
}
else set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
}
+
+/* retrieve a pointer to a device_notification from its handle */
+static inline struct device_notification *get_device_notification( user_handle_t handle )
+{
+ struct device_notification *ret = get_user_object( handle, USER_DEVNOTIFY );
+ if (!ret) set_win32_error( ERROR_INVALID_HANDLE );
+ return ret;
+}
+
+/* create a new device notification structure and link it into the global list */
+static struct device_notification *register_device_notification( struct window *recipient )
+{
+ struct device_notification *notification;
+
+ if (!recipient)
+ {
+ return NULL;
+ }
+
+ if (!(notification = mem_alloc( sizeof(*notification) ))) goto failed;
+ if (!(notification->handle = alloc_user_handle( notification, USER_DEVNOTIFY ))) goto failed;
+
+ notification->recipient = recipient->handle;
+ /* FIXME: Add support for notification filters */
+
+ list_add_tail( &device_notifications, ¬ification->entry );
+
+ return notification;
+failed:
+ if (notification)
+ {
+ if (notification->handle) free_user_handle( notification->handle );
+ free( notification );
+ }
+
+ return NULL;
+}
+
+static void unregister_device_notification( struct device_notification *notification)
+{
+ list_remove( ¬ification->entry );
+ free_user_handle( notification->handle );
+ memset( notification, 0x55, sizeof(*notification) );
+ free( notification );
+}
+
+static int get_device_notifications( struct user_handle_array *array )
+{
+ struct device_notification *notification;
+
+ LIST_FOR_EACH_ENTRY( notification, &device_notifications, struct device_notification, entry )
+ {
+ /* FIXME: Implement notification filtering */
+ if (!add_handle_to_array( array, notification->recipient )) return 0;
+ }
+
+ return 1;
+}
+
+/* register for device notifications */
+DECL_HANDLER(register_device_notification)
+{
+ struct device_notification *notification = NULL;
+ struct window *recipient = get_window( req->recipient );
+
+ reply->handle = 0;
+ if (!recipient) return;
+
+ if (!(notification = register_device_notification( recipient ))) return;
+
+ reply->handle = notification->handle;
+}
+
+DECL_HANDLER(unregister_device_notification)
+{
+ struct device_notification *notification = get_device_notification( req->notification );
+ if (notification) unregister_device_notification(notification);
+}
+
+DECL_HANDLER(get_device_notifications)
+{
+ struct user_handle_array array;
+ data_size_t len;
+
+ array.handles = NULL;
+ array.count = 0;
+ array.total = 0;
+
+ if (!get_device_notifications( &array )) return;
+
+ reply->count = array.count;
+ len = min( get_reply_max_size(), array.count * sizeof(user_handle_t) );
+ if (len) set_reply_data_ptr( array.handles, len );
+ else free( array.handles );
+}
+
--
2.21.0
More information about the wine-devel
mailing list