2001-08-28 11:44:52 -07:00
|
|
|
/*
|
|
|
|
* Wine server USER definitions
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001 Alexandre Julliard
|
2002-03-09 16:29:33 -07:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-05-18 05:49:52 -07:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2001-08-28 11:44:52 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __WINE_SERVER_USER_H
|
|
|
|
#define __WINE_SERVER_USER_H
|
|
|
|
|
2024-10-23 02:53:04 -07:00
|
|
|
#include <limits.h>
|
2001-08-28 11:44:52 -07:00
|
|
|
#include "wine/server_protocol.h"
|
2024-02-21 12:11:55 -07:00
|
|
|
#include "unicode.h"
|
2001-08-28 11:44:52 -07:00
|
|
|
|
|
|
|
struct thread;
|
2004-06-23 13:44:58 -07:00
|
|
|
struct region;
|
2001-08-28 11:44:52 -07:00
|
|
|
struct window;
|
2001-11-13 15:23:48 -07:00
|
|
|
struct msg_queue;
|
2003-07-03 11:16:48 -07:00
|
|
|
struct hook_table;
|
2003-12-09 21:08:06 -07:00
|
|
|
struct window_class;
|
2005-07-07 04:29:23 -07:00
|
|
|
struct atom_table;
|
2005-06-29 13:13:36 -07:00
|
|
|
struct clipboard;
|
2001-08-28 11:44:52 -07:00
|
|
|
|
|
|
|
enum user_object
|
|
|
|
{
|
2002-10-28 17:41:42 -07:00
|
|
|
USER_WINDOW = 1,
|
2009-10-12 05:25:01 -07:00
|
|
|
USER_HOOK,
|
|
|
|
USER_CLIENT /* arbitrary client handle */
|
2001-08-28 11:44:52 -07:00
|
|
|
};
|
|
|
|
|
2005-07-08 04:37:40 -07:00
|
|
|
#define DESKTOP_ATOM ((atom_t)32769)
|
|
|
|
|
2005-07-11 03:55:53 -07:00
|
|
|
struct winstation
|
|
|
|
{
|
|
|
|
struct object obj; /* object header */
|
|
|
|
unsigned int flags; /* winstation flags */
|
|
|
|
struct list entry; /* entry in global winstation list */
|
|
|
|
struct list desktops; /* list of desktops of this winstation */
|
2024-01-27 13:03:41 -07:00
|
|
|
struct desktop *input_desktop; /* desktop receiving user input */
|
2005-07-11 03:55:53 -07:00
|
|
|
struct clipboard *clipboard; /* clipboard information */
|
|
|
|
struct atom_table *atom_table; /* global atom table */
|
2016-01-20 06:27:44 -07:00
|
|
|
struct namespace *desktop_names; /* namespace for desktops of this winstation */
|
2024-09-25 02:07:40 -07:00
|
|
|
unsigned int monitor_count; /* number of monitors */
|
|
|
|
struct monitor_info *monitors; /* window station monitors */
|
2005-07-11 03:55:53 -07:00
|
|
|
};
|
|
|
|
|
2024-05-27 02:48:52 -07:00
|
|
|
struct key_repeat
|
|
|
|
{
|
|
|
|
int enable; /* enable auto-repeat */
|
|
|
|
timeout_t delay; /* auto-repeat delay */
|
|
|
|
timeout_t period; /* auto-repeat period */
|
2024-11-18 13:32:53 -07:00
|
|
|
union hw_input input; /* the input to repeat */
|
2024-05-27 02:48:52 -07:00
|
|
|
user_handle_t win; /* target window for input event */
|
|
|
|
struct timeout_user *timeout; /* timeout for repeat */
|
|
|
|
};
|
|
|
|
|
2005-07-11 03:55:53 -07:00
|
|
|
struct desktop
|
|
|
|
{
|
2011-02-24 08:45:04 -07:00
|
|
|
struct object obj; /* object header */
|
|
|
|
struct winstation *winstation; /* winstation this desktop belongs to */
|
2024-01-27 13:03:41 -07:00
|
|
|
timeout_t input_time; /* last time this desktop had the input */
|
2011-02-24 08:45:04 -07:00
|
|
|
struct list entry; /* entry in winstation list of desktops */
|
2024-01-27 14:00:12 -07:00
|
|
|
struct list threads; /* list of threads connected to this desktop */
|
2011-02-24 08:45:04 -07:00
|
|
|
struct window *top_window; /* desktop window for this desktop */
|
|
|
|
struct window *msg_window; /* HWND_MESSAGE top window */
|
2024-09-26 11:55:51 -07:00
|
|
|
struct window *shell_window; /* shell window for this desktop */
|
|
|
|
struct window *shell_listview; /* shell list view window for this desktop */
|
|
|
|
struct window *progman_window; /* progman window for this desktop */
|
|
|
|
struct window *taskman_window; /* taskman window for this desktop */
|
2011-02-24 08:45:04 -07:00
|
|
|
struct hook_table *global_hooks; /* table of global hooks on this desktop */
|
2011-05-26 13:52:17 -07:00
|
|
|
struct list hotkeys; /* list of registered hotkeys */
|
2021-10-04 11:57:55 -07:00
|
|
|
struct list pointers; /* list of active pointers */
|
2011-02-24 08:45:04 -07:00
|
|
|
struct timeout_user *close_timeout; /* timeout before closing the desktop */
|
|
|
|
struct thread_input *foreground_input; /* thread input of foreground thread */
|
|
|
|
unsigned int users; /* processes and threads using this desktop */
|
2011-02-25 04:10:04 -07:00
|
|
|
unsigned char keystate[256]; /* asynchronous key state */
|
2024-06-20 14:59:52 -07:00
|
|
|
unsigned char alt_pressed; /* last key press was Alt (used to determine msg on release) */
|
2024-05-27 02:48:52 -07:00
|
|
|
struct key_repeat key_repeat; /* key auto-repeat */
|
2024-02-19 14:27:55 -07:00
|
|
|
unsigned int clip_flags; /* last cursor clip flags */
|
|
|
|
user_handle_t cursor_win; /* window that contains the cursor */
|
2024-05-07 00:52:18 -07:00
|
|
|
const desktop_shm_t *shared; /* desktop session shared memory */
|
2005-07-11 03:55:53 -07:00
|
|
|
};
|
|
|
|
|
2001-08-28 11:44:52 -07:00
|
|
|
/* user handles functions */
|
|
|
|
|
|
|
|
extern user_handle_t alloc_user_handle( void *ptr, enum user_object type );
|
|
|
|
extern void *get_user_object( user_handle_t handle, enum user_object type );
|
|
|
|
extern void *get_user_object_handle( user_handle_t *handle, enum user_object type );
|
2001-09-12 10:09:24 -07:00
|
|
|
extern user_handle_t get_user_full_handle( user_handle_t handle );
|
2001-08-28 11:44:52 -07:00
|
|
|
extern void *free_user_handle( user_handle_t handle );
|
|
|
|
extern void *next_user_handle( user_handle_t *handle, enum user_object type );
|
2009-10-15 08:56:04 -07:00
|
|
|
extern void free_process_user_handles( struct process *process );
|
2001-08-28 11:44:52 -07:00
|
|
|
|
2003-06-23 16:02:02 -07:00
|
|
|
/* clipboard functions */
|
|
|
|
|
2016-08-23 04:58:44 -07:00
|
|
|
extern void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window );
|
2003-06-23 16:02:02 -07:00
|
|
|
extern void cleanup_clipboard_thread( struct thread *thread );
|
|
|
|
|
2002-11-20 12:54:32 -07:00
|
|
|
/* hook functions */
|
|
|
|
|
2003-07-11 14:55:58 -07:00
|
|
|
extern void remove_thread_hooks( struct thread *thread );
|
2005-05-11 06:03:15 -07:00
|
|
|
extern unsigned int get_active_hooks(void);
|
2024-05-29 00:34:54 -07:00
|
|
|
extern struct thread *get_first_global_hook( struct desktop *desktop, int id );
|
2024-06-24 14:35:06 -07:00
|
|
|
extern void add_desktop_hook_count( struct desktop *desktop, struct thread *thread, int count );
|
2002-11-20 12:54:32 -07:00
|
|
|
|
2001-08-28 11:44:52 -07:00
|
|
|
/* queue functions */
|
|
|
|
|
2002-08-16 16:30:41 -07:00
|
|
|
extern void free_msg_queue( struct thread *thread );
|
2003-07-03 11:16:48 -07:00
|
|
|
extern struct hook_table *get_queue_hooks( struct thread *thread );
|
|
|
|
extern void set_queue_hooks( struct thread *thread, struct hook_table *hooks );
|
2024-06-24 14:35:06 -07:00
|
|
|
extern void add_queue_hook_count( struct thread *thread, unsigned int index, int count );
|
2001-11-13 15:23:48 -07:00
|
|
|
extern void inc_queue_paint_count( struct thread *thread, int incr );
|
2001-08-28 11:44:52 -07:00
|
|
|
extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
|
2005-04-26 07:31:33 -07:00
|
|
|
extern int init_thread_queue( struct thread *thread );
|
2024-06-04 13:40:46 -07:00
|
|
|
extern void check_thread_queue_idle( struct thread *thread );
|
2002-10-11 11:50:15 -07:00
|
|
|
extern int attach_thread_input( struct thread *thread_from, struct thread *thread_to );
|
2005-07-11 06:30:23 -07:00
|
|
|
extern void detach_thread_input( struct thread *thread_from );
|
2023-06-15 23:54:43 -07:00
|
|
|
extern void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect,
|
|
|
|
unsigned int flags, int reset );
|
2024-10-21 15:11:43 -07:00
|
|
|
extern void update_cursor_pos( struct desktop *desktop );
|
2002-03-23 13:43:52 -07:00
|
|
|
extern void post_message( user_handle_t win, unsigned int message,
|
2008-12-10 08:01:50 -07:00
|
|
|
lparam_t wparam, lparam_t lparam );
|
2016-08-30 00:33:04 -07:00
|
|
|
extern void send_notify_message( user_handle_t win, unsigned int message,
|
|
|
|
lparam_t wparam, lparam_t lparam );
|
2005-02-03 09:40:20 -07:00
|
|
|
extern void post_win_event( struct thread *thread, unsigned int event,
|
|
|
|
user_handle_t win, unsigned int object_id,
|
2008-12-29 09:35:35 -07:00
|
|
|
unsigned int child_id, client_ptr_t proc,
|
2006-07-26 01:43:25 -07:00
|
|
|
const WCHAR *module, data_size_t module_size,
|
2005-02-03 09:40:20 -07:00
|
|
|
user_handle_t handle );
|
2011-05-26 13:52:17 -07:00
|
|
|
extern void free_hotkeys( struct desktop *desktop, user_handle_t window );
|
2021-10-04 11:57:55 -07:00
|
|
|
extern void free_pointers( struct desktop *desktop );
|
2024-02-25 01:53:09 -07:00
|
|
|
extern void set_rawinput_process( struct process *process, int enable );
|
2001-08-28 11:44:52 -07:00
|
|
|
|
2004-06-23 13:44:58 -07:00
|
|
|
/* region functions */
|
|
|
|
|
2005-02-22 12:42:35 -07:00
|
|
|
extern struct region *create_empty_region(void);
|
2006-07-26 01:43:25 -07:00
|
|
|
extern struct region *create_region_from_req_data( const void *data, data_size_t size );
|
2004-06-23 13:44:58 -07:00
|
|
|
extern void free_region( struct region *region );
|
|
|
|
extern void set_region_rect( struct region *region, const rectangle_t *rect );
|
2006-07-26 01:43:25 -07:00
|
|
|
extern rectangle_t *get_region_data( const struct region *region, data_size_t max_size,
|
|
|
|
data_size_t *total_size );
|
|
|
|
extern rectangle_t *get_region_data_and_free( struct region *region, data_size_t max_size,
|
|
|
|
data_size_t *total_size );
|
2004-06-23 13:44:58 -07:00
|
|
|
extern int is_region_empty( const struct region *region );
|
2022-10-31 06:29:52 -07:00
|
|
|
extern int is_region_equal( const struct region *region1, const struct region *region2 );
|
2004-06-23 13:44:58 -07:00
|
|
|
extern void get_region_extents( const struct region *region, rectangle_t *rect );
|
|
|
|
extern void offset_region( struct region *region, int x, int y );
|
2010-09-27 11:46:41 -07:00
|
|
|
extern void mirror_region( const rectangle_t *client_rect, struct region *region );
|
2018-08-24 03:45:43 -07:00
|
|
|
extern void scale_region( struct region *region, unsigned int dpi_from, unsigned int dpi_to );
|
2004-06-23 13:44:58 -07:00
|
|
|
extern struct region *copy_region( struct region *dst, const struct region *src );
|
|
|
|
extern struct region *intersect_region( struct region *dst, const struct region *src1,
|
|
|
|
const struct region *src2 );
|
|
|
|
extern struct region *subtract_region( struct region *dst, const struct region *src1,
|
|
|
|
const struct region *src2 );
|
|
|
|
extern struct region *union_region( struct region *dst, const struct region *src1,
|
|
|
|
const struct region *src2 );
|
2004-09-07 18:34:22 -07:00
|
|
|
extern struct region *xor_region( struct region *dst, const struct region *src1,
|
|
|
|
const struct region *src2 );
|
2004-07-20 15:17:38 -07:00
|
|
|
extern int point_in_region( struct region *region, int x, int y );
|
2004-09-01 15:49:14 -07:00
|
|
|
extern int rect_in_region( struct region *region, const rectangle_t *rect );
|
2004-06-23 13:44:58 -07:00
|
|
|
|
2001-08-28 11:44:52 -07:00
|
|
|
/* window functions */
|
|
|
|
|
2006-03-06 13:02:24 -07:00
|
|
|
extern struct process *get_top_window_owner( struct desktop *desktop );
|
2024-10-23 02:53:04 -07:00
|
|
|
extern void get_virtual_screen_rect( struct desktop *desktop, rectangle_t *rect, int is_raw );
|
2011-03-31 11:25:45 -07:00
|
|
|
extern void post_desktop_message( struct desktop *desktop, unsigned int message,
|
|
|
|
lparam_t wparam, lparam_t lparam );
|
2022-02-08 05:12:43 -07:00
|
|
|
extern void free_window_handle( struct window *win );
|
2001-08-28 11:44:52 -07:00
|
|
|
extern void destroy_thread_windows( struct thread *thread );
|
2001-09-21 14:08:40 -07:00
|
|
|
extern int is_child_window( user_handle_t parent, user_handle_t child );
|
2014-03-27 06:59:51 -07:00
|
|
|
extern int is_valid_foreground_window( user_handle_t window );
|
2004-10-27 14:54:41 -07:00
|
|
|
extern int is_window_visible( user_handle_t window );
|
2010-06-11 03:20:41 -07:00
|
|
|
extern int is_window_transparent( user_handle_t window );
|
2002-10-11 16:41:06 -07:00
|
|
|
extern int make_window_active( user_handle_t window );
|
2002-03-23 13:43:52 -07:00
|
|
|
extern struct thread *get_window_thread( user_handle_t handle );
|
2014-10-14 04:28:47 -07:00
|
|
|
extern user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y );
|
|
|
|
extern struct thread *window_thread_from_point( user_handle_t scope, int x, int y );
|
2001-11-14 14:28:36 -07:00
|
|
|
extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
|
2003-12-09 21:08:06 -07:00
|
|
|
extern struct window_class *get_window_class( user_handle_t window );
|
|
|
|
|
|
|
|
/* window class functions */
|
|
|
|
|
|
|
|
extern void destroy_process_classes( struct process *process );
|
2003-12-10 22:34:53 -07:00
|
|
|
extern struct window_class *grab_class( struct process *process, atom_t atom,
|
2008-12-29 08:41:44 -07:00
|
|
|
mod_handle_t instance, int *extra_bytes );
|
2003-12-09 21:08:06 -07:00
|
|
|
extern void release_class( struct window_class *class );
|
2006-03-06 12:37:52 -07:00
|
|
|
extern int is_desktop_class( struct window_class *class );
|
2008-06-25 05:43:39 -07:00
|
|
|
extern int is_hwnd_message_class( struct window_class *class );
|
2022-10-31 06:29:52 -07:00
|
|
|
extern int get_class_style( struct window_class *class );
|
2003-12-09 21:08:06 -07:00
|
|
|
extern atom_t get_class_atom( struct window_class *class );
|
2008-12-29 09:24:33 -07:00
|
|
|
extern client_ptr_t get_class_client_ptr( struct window_class *class );
|
2001-08-28 11:44:52 -07:00
|
|
|
|
2005-06-08 11:44:50 -07:00
|
|
|
/* windows station functions */
|
|
|
|
|
2024-02-25 01:33:06 -07:00
|
|
|
extern struct winstation *get_visible_winstation(void);
|
|
|
|
extern struct desktop *get_input_desktop( struct winstation *winstation );
|
|
|
|
extern int set_input_desktop( struct winstation *winstation, struct desktop *new_desktop );
|
2008-03-18 07:17:40 -07:00
|
|
|
extern struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access );
|
2005-06-29 13:13:36 -07:00
|
|
|
extern struct winstation *get_process_winstation( struct process *process, unsigned int access );
|
2005-07-11 03:55:53 -07:00
|
|
|
extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
|
2024-02-21 12:11:55 -07:00
|
|
|
extern void connect_process_winstation( struct process *process, struct unicode_str *desktop_path,
|
|
|
|
struct thread *parent_thread, struct process *parent_process );
|
2006-03-27 03:57:17 -07:00
|
|
|
extern void set_process_default_desktop( struct process *process, struct desktop *desktop,
|
|
|
|
obj_handle_t handle );
|
2006-03-06 13:02:24 -07:00
|
|
|
extern void close_process_desktop( struct process *process );
|
server: Track desktop users per thread instead of per process.
As some thread may use a different desktop from their process.
This fixes the user32 win tests, which leaks a desktop that never gets
closed. The test_shell_window test creates a new desktop, which spawns
explorer.exe process, incrementing the desktop user count to 1, then
associates the desktop to a thread, which closes it on exit.
Never the user count is incremented to 2, and closing the thread desktop
doesn't either check whether the desktop process should be terminated.
Reversely, it is possible to create a desktop, associate it with a
thread /and/ a process, and this time the desktop process would be
terminated when the process exits, although the thread may still be
using it.
Tracking the users per thread is more robust and fixes the problem as
set_thread_desktop increments the desktop user count, and thread exit
decrements it.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
2021-04-21 01:38:15 -07:00
|
|
|
extern void set_thread_default_desktop( struct thread *thread, struct desktop *desktop, obj_handle_t handle );
|
|
|
|
extern void release_thread_desktop( struct thread *thread, int close );
|
2005-06-08 11:44:50 -07:00
|
|
|
|
2022-10-31 06:29:52 -07:00
|
|
|
/* checks if two rectangles are identical */
|
|
|
|
static inline int is_rect_equal( const rectangle_t *rect1, const rectangle_t *rect2 )
|
|
|
|
{
|
|
|
|
return (rect1->left == rect2->left && rect1->right == rect2->right &&
|
|
|
|
rect1->top == rect2->top && rect1->bottom == rect2->bottom);
|
|
|
|
}
|
|
|
|
|
2018-07-05 03:46:18 -07:00
|
|
|
static inline int is_rect_empty( const rectangle_t *rect )
|
|
|
|
{
|
|
|
|
return (rect->left >= rect->right || rect->top >= rect->bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int point_in_rect( const rectangle_t *rect, int x, int y )
|
|
|
|
{
|
|
|
|
return (x >= rect->left && x < rect->right && y >= rect->top && y < rect->bottom);
|
|
|
|
}
|
|
|
|
|
2018-08-24 03:06:45 -07:00
|
|
|
static inline int scale_dpi( int val, unsigned int dpi_from, unsigned int dpi_to )
|
|
|
|
{
|
|
|
|
if (val >= 0) return (val * dpi_to + (dpi_from / 2)) / dpi_from;
|
|
|
|
return (val * dpi_to - (dpi_from / 2)) / dpi_from;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void scale_dpi_rect( rectangle_t *rect, unsigned int dpi_from, unsigned int dpi_to )
|
|
|
|
{
|
|
|
|
rect->left = scale_dpi( rect->left, dpi_from, dpi_to );
|
|
|
|
rect->top = scale_dpi( rect->top, dpi_from, dpi_to );
|
|
|
|
rect->right = scale_dpi( rect->right, dpi_from, dpi_to );
|
|
|
|
rect->bottom = scale_dpi( rect->bottom, dpi_from, dpi_to );
|
|
|
|
}
|
|
|
|
|
2018-07-05 03:46:18 -07:00
|
|
|
/* offset the coordinates of a rectangle */
|
|
|
|
static inline void offset_rect( rectangle_t *rect, int offset_x, int offset_y )
|
|
|
|
{
|
|
|
|
rect->left += offset_x;
|
|
|
|
rect->top += offset_y;
|
|
|
|
rect->right += offset_x;
|
|
|
|
rect->bottom += offset_y;
|
|
|
|
}
|
|
|
|
|
2010-09-27 11:46:41 -07:00
|
|
|
/* mirror a rectangle respective to the window client area */
|
|
|
|
static inline void mirror_rect( const rectangle_t *client_rect, rectangle_t *rect )
|
|
|
|
{
|
|
|
|
int width = client_rect->right - client_rect->left;
|
|
|
|
int tmp = rect->left;
|
|
|
|
rect->left = width - rect->right;
|
|
|
|
rect->right = width - tmp;
|
|
|
|
}
|
|
|
|
|
2011-02-25 03:31:47 -07:00
|
|
|
/* compute the intersection of two rectangles; return 0 if the result is empty */
|
|
|
|
static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, const rectangle_t *src2 )
|
|
|
|
{
|
|
|
|
dst->left = max( src1->left, src2->left );
|
|
|
|
dst->top = max( src1->top, src2->top );
|
|
|
|
dst->right = min( src1->right, src2->right );
|
|
|
|
dst->bottom = min( src1->bottom, src2->bottom );
|
2018-07-05 03:46:18 -07:00
|
|
|
return !is_rect_empty( dst );
|
2011-02-25 03:31:47 -07:00
|
|
|
}
|
|
|
|
|
2024-10-23 02:53:04 -07:00
|
|
|
static inline void reset_bounds( rectangle_t *bounds )
|
|
|
|
{
|
|
|
|
bounds->left = bounds->top = INT_MAX;
|
|
|
|
bounds->right = bounds->bottom = INT_MIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void union_rect( rectangle_t *dest, const rectangle_t *src1, const rectangle_t *src2 )
|
|
|
|
{
|
|
|
|
if (is_rect_empty( src1 ))
|
|
|
|
{
|
|
|
|
if (is_rect_empty( src2 ))
|
|
|
|
{
|
|
|
|
reset_bounds( dest );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else *dest = *src2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (is_rect_empty( src2 )) *dest = *src1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dest->left = min( src1->left, src2->left );
|
|
|
|
dest->right = max( src1->right, src2->right );
|
|
|
|
dest->top = min( src1->top, src2->top );
|
|
|
|
dest->bottom = max( src1->bottom, src2->bottom );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-30 02:08:36 -07:00
|
|
|
/* validate a window handle and return the full handle */
|
|
|
|
static inline user_handle_t get_valid_window_handle( user_handle_t win )
|
|
|
|
{
|
|
|
|
if (get_user_object_handle( &win, USER_WINDOW )) return win;
|
|
|
|
set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-08-28 11:44:52 -07:00
|
|
|
#endif /* __WINE_SERVER_USER_H */
|