Commit 805bdc53 authored by Alexandre Julliard's avatar Alexandre Julliard

Store the window caption text in the server.

Maintain a paint count separately for each window.
parent e5fe7798
......@@ -1325,15 +1325,6 @@ struct get_msg_queue_request
struct inc_queue_paint_count_request
{
struct request_header __header;
void* id;
int incr;
};
struct set_queue_mask_request
{
struct request_header __header;
......@@ -1721,6 +1712,33 @@ struct get_window_rectangles_request
struct get_window_text_request
{
struct request_header __header;
user_handle_t handle;
/* VARARG(text,unicode_str); */
};
struct set_window_text_request
{
struct request_header __header;
user_handle_t handle;
/* VARARG(text,unicode_str); */
};
struct inc_window_paint_count_request
{
struct request_header __header;
user_handle_t handle;
int incr;
};
struct get_windows_offset_request
{
struct request_header __header;
......@@ -1875,7 +1893,6 @@ enum request
REQ_get_atom_name,
REQ_init_atom_table,
REQ_get_msg_queue,
REQ_inc_queue_paint_count,
REQ_set_queue_mask,
REQ_get_queue_status,
REQ_wait_input_idle,
......@@ -1906,6 +1923,9 @@ enum request
REQ_get_window_tree,
REQ_set_window_rectangles,
REQ_get_window_rectangles,
REQ_get_window_text,
REQ_set_window_text,
REQ_inc_window_paint_count,
REQ_get_windows_offset,
REQ_set_window_property,
REQ_remove_window_property,
......@@ -2020,7 +2040,6 @@ union generic_request
struct get_atom_name_request get_atom_name;
struct init_atom_table_request init_atom_table;
struct get_msg_queue_request get_msg_queue;
struct inc_queue_paint_count_request inc_queue_paint_count;
struct set_queue_mask_request set_queue_mask;
struct get_queue_status_request get_queue_status;
struct wait_input_idle_request wait_input_idle;
......@@ -2051,6 +2070,9 @@ union generic_request
struct get_window_tree_request get_window_tree;
struct set_window_rectangles_request set_window_rectangles;
struct get_window_rectangles_request get_window_rectangles;
struct get_window_text_request get_window_text;
struct set_window_text_request set_window_text;
struct inc_window_paint_count_request inc_window_paint_count;
struct get_windows_offset_request get_windows_offset;
struct set_window_property_request set_window_property;
struct remove_window_property_request remove_window_property;
......@@ -2058,6 +2080,6 @@ union generic_request
struct get_window_properties_request get_window_properties;
};
#define SERVER_PROTOCOL_VERSION 63
#define SERVER_PROTOCOL_VERSION 64
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -1188,13 +1188,6 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
@END
/* Increment the message queue paint count */
@REQ(inc_queue_paint_count)
void* id; /* thread id */
int incr; /* increment (can be negative) */
@END
/* Set the current message queue wakeup mask */
@REQ(set_queue_mask)
unsigned int wake_mask; /* wakeup bits mask */
......@@ -1542,6 +1535,28 @@ enum message_type
@END
/* Get the window text */
@REQ(get_window_text)
user_handle_t handle; /* handle to the window */
@REPLY
VARARG(text,unicode_str); /* window text */
@END
/* Set the window text */
@REQ(set_window_text)
user_handle_t handle; /* handle to the window */
VARARG(text,unicode_str); /* window text */
@END
/* Increment the window paint count */
@REQ(inc_window_paint_count)
user_handle_t handle; /* handle to the window */
int incr; /* increment (can be negative) */
@END
/* Get the coordinates offset between two windows */
@REQ(get_windows_offset)
user_handle_t from; /* handle to the first window */
......
......@@ -175,7 +175,7 @@ inline static int get_hardware_msg_bit( struct message *msg )
}
/* get the current thread queue, creating it if needed */
inline struct msg_queue *get_current_queue(void)
inline static struct msg_queue *get_current_queue(void)
{
struct msg_queue *queue = current->queue;
if (!queue) queue = create_msg_queue( current );
......@@ -598,6 +598,23 @@ static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
return timer;
}
/* increment (or decrement if 'incr' is negative) the queue paint count */
void inc_queue_paint_count( struct thread *thread, int incr )
{
struct msg_queue *queue = thread->queue;
assert( queue );
if ((queue->paint_count += incr) < 0) queue->paint_count = 0;
if (queue->paint_count)
set_queue_bits( queue, QS_PAINT );
else
clear_queue_bits( queue, QS_PAINT );
}
/* remove all messages and timers belonging to a certain window */
void queue_cleanup_window( struct thread *thread, user_handle_t win )
{
......@@ -644,30 +661,6 @@ DECL_HANDLER(get_msg_queue)
}
/* increment the message queue paint count */
DECL_HANDLER(inc_queue_paint_count)
{
struct msg_queue *queue;
struct thread *thread = get_thread_from_id( req->id );
if (!thread) return;
if ((queue = thread->queue))
{
if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
if (queue->paint_count)
set_queue_bits( queue, QS_PAINT );
else
clear_queue_bits( queue, QS_PAINT );
}
else set_error( STATUS_INVALID_PARAMETER );
release_object( thread );
}
/* set the current message queue wakeup mask */
DECL_HANDLER(set_queue_mask)
{
......
......@@ -168,7 +168,6 @@ DECL_HANDLER(find_atom);
DECL_HANDLER(get_atom_name);
DECL_HANDLER(init_atom_table);
DECL_HANDLER(get_msg_queue);
DECL_HANDLER(inc_queue_paint_count);
DECL_HANDLER(set_queue_mask);
DECL_HANDLER(get_queue_status);
DECL_HANDLER(wait_input_idle);
......@@ -199,6 +198,9 @@ DECL_HANDLER(get_window_children);
DECL_HANDLER(get_window_tree);
DECL_HANDLER(set_window_rectangles);
DECL_HANDLER(get_window_rectangles);
DECL_HANDLER(get_window_text);
DECL_HANDLER(set_window_text);
DECL_HANDLER(inc_window_paint_count);
DECL_HANDLER(get_windows_offset);
DECL_HANDLER(set_window_property);
DECL_HANDLER(remove_window_property);
......@@ -312,7 +314,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_atom_name,
(req_handler)req_init_atom_table,
(req_handler)req_get_msg_queue,
(req_handler)req_inc_queue_paint_count,
(req_handler)req_set_queue_mask,
(req_handler)req_get_queue_status,
(req_handler)req_wait_input_idle,
......@@ -343,6 +344,9 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_window_tree,
(req_handler)req_set_window_rectangles,
(req_handler)req_get_window_rectangles,
(req_handler)req_get_window_text,
(req_handler)req_set_window_text,
(req_handler)req_inc_window_paint_count,
(req_handler)req_get_windows_offset,
(req_handler)req_set_window_property,
(req_handler)req_remove_window_property,
......
......@@ -1456,12 +1456,6 @@ static void dump_get_msg_queue_reply( const struct get_msg_queue_request *req )
fprintf( stderr, " handle=%d", req->handle );
}
static void dump_inc_queue_paint_count_request( const struct inc_queue_paint_count_request *req )
{
fprintf( stderr, " id=%p,", req->id );
fprintf( stderr, " incr=%d", req->incr );
}
static void dump_set_queue_mask_request( const struct set_queue_mask_request *req )
{
fprintf( stderr, " wake_mask=%08x,", req->wake_mask );
......@@ -1832,6 +1826,30 @@ static void dump_get_window_rectangles_reply( const struct get_window_rectangles
dump_rectangle( req, &req->client );
}
static void dump_get_window_text_request( const struct get_window_text_request *req )
{
fprintf( stderr, " handle=%08x", req->handle );
}
static void dump_get_window_text_reply( const struct get_window_text_request *req )
{
fprintf( stderr, " text=" );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_set_window_text_request( const struct set_window_text_request *req )
{
fprintf( stderr, " handle=%08x,", req->handle );
fprintf( stderr, " text=" );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_inc_window_paint_count_request( const struct inc_window_paint_count_request *req )
{
fprintf( stderr, " handle=%08x,", req->handle );
fprintf( stderr, " incr=%d", req->incr );
}
static void dump_get_windows_offset_request( const struct get_windows_offset_request *req )
{
fprintf( stderr, " from=%08x,", req->from );
......@@ -1988,7 +2006,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_atom_name_request,
(dump_func)dump_init_atom_table_request,
(dump_func)dump_get_msg_queue_request,
(dump_func)dump_inc_queue_paint_count_request,
(dump_func)dump_set_queue_mask_request,
(dump_func)dump_get_queue_status_request,
(dump_func)dump_wait_input_idle_request,
......@@ -2019,6 +2036,9 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_window_tree_request,
(dump_func)dump_set_window_rectangles_request,
(dump_func)dump_get_window_rectangles_request,
(dump_func)dump_get_window_text_request,
(dump_func)dump_set_window_text_request,
(dump_func)dump_inc_window_paint_count_request,
(dump_func)dump_get_windows_offset_request,
(dump_func)dump_set_window_property_request,
(dump_func)dump_remove_window_property_request,
......@@ -2129,7 +2149,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_atom_name_reply,
(dump_func)0,
(dump_func)dump_get_msg_queue_reply,
(dump_func)0,
(dump_func)dump_set_queue_mask_reply,
(dump_func)dump_get_queue_status_reply,
(dump_func)dump_wait_input_idle_reply,
......@@ -2160,6 +2179,9 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_window_tree_reply,
(dump_func)0,
(dump_func)dump_get_window_rectangles_reply,
(dump_func)dump_get_window_text_reply,
(dump_func)0,
(dump_func)0,
(dump_func)dump_get_windows_offset_reply,
(dump_func)0,
(dump_func)dump_remove_window_property_reply,
......@@ -2270,7 +2292,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_atom_name",
"init_atom_table",
"get_msg_queue",
"inc_queue_paint_count",
"set_queue_mask",
"get_queue_status",
"wait_input_idle",
......@@ -2301,6 +2322,9 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_window_tree",
"set_window_rectangles",
"get_window_rectangles",
"get_window_text",
"set_window_text",
"inc_window_paint_count",
"get_windows_offset",
"set_window_property",
"remove_window_property",
......
......@@ -7,6 +7,8 @@
#ifndef __WINE_SERVER_UNICODE_H
#define __WINE_SERVER_UNICODE_H
#include <stdio.h>
#include "windef.h"
#include "wine/unicode.h"
#include "object.h"
......
......@@ -11,6 +11,7 @@
struct thread;
struct window;
struct msg_queue;
enum user_object
{
......@@ -28,6 +29,7 @@ extern void *next_user_handle( user_handle_t *handle, enum user_object type );
/* queue functions */
extern void inc_queue_paint_count( struct thread *thread, int incr );
extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
/* window functions */
......
......@@ -11,6 +11,7 @@
#include "thread.h"
#include "process.h"
#include "user.h"
#include "unicode.h"
/* a window property */
struct property
......@@ -47,6 +48,8 @@ struct window
unsigned int id; /* window id */
void* instance; /* creator instance */
void* user_data; /* user-specific data */
WCHAR *text; /* window caption text */
int paint_count; /* count of pending paints for this window */
int prop_inuse; /* number of in-use window properties */
int prop_alloc; /* number of allocated window properties */
struct property *properties; /* window properties array */
......@@ -244,10 +247,12 @@ static void destroy_window( struct window *win )
if (ptr->owner == win) ptr->owner = NULL;
}
if (win->thread->queue) queue_cleanup_window( win->thread, win->handle );
if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
queue_cleanup_window( win->thread, win->handle );
free_user_handle( win->handle );
destroy_properties( win );
unlink_window( win );
if (win->text) free( win->text );
memset( win, 0x55, sizeof(*win) );
free( win );
}
......@@ -275,6 +280,8 @@ static struct window *create_window( struct window *parent, struct window *owner
win->id = 0;
win->instance = NULL;
win->user_data = NULL;
win->text = NULL;
win->paint_count = 0;
win->prop_inuse = 0;
win->prop_alloc = 0;
win->properties = NULL;
......@@ -563,6 +570,57 @@ DECL_HANDLER(get_window_rectangles)
}
/* get the window text */
DECL_HANDLER(get_window_text)
{
struct window *win = get_window( req->handle );
size_t len = 0;
if (win && win->text)
{
len = strlenW( win->text ) * sizeof(WCHAR);
if (len > get_req_data_size(req)) len = get_req_data_size(req);
memcpy( get_req_data(req), win->text, len );
}
set_req_data_size( req, len );
}
/* set the window text */
DECL_HANDLER(set_window_text)
{
struct window *win = get_window( req->handle );
if (win)
{
WCHAR *text = NULL;
size_t len = get_req_data_size(req) / sizeof(WCHAR);
if (len)
{
if (!(text = mem_alloc( (len+1) * sizeof(WCHAR) ))) return;
memcpy( text, get_req_data(req), len * sizeof(WCHAR) );
text[len] = 0;
}
if (win->text) free( win->text );
win->text = text;
}
}
/* increment the window paint count */
DECL_HANDLER(inc_window_paint_count)
{
struct window *win = get_window( req->handle );
if (win)
{
int old = win->paint_count;
if ((win->paint_count += req->incr) < 0) win->paint_count = 0;
inc_queue_paint_count( win->thread, win->paint_count - old );
}
}
/* get the coordinates offset between two windows */
DECL_HANDLER(get_windows_offset)
{
......
......@@ -19,6 +19,7 @@
#include "winnls.h"
#include "wine/unicode.h"
#include "wine/winuser16.h"
#include "wine/server.h"
#include "imm.h"
DEFAULT_DEBUG_CHANNEL(win);
......@@ -71,13 +72,23 @@ static void DEFWND_SetTextA( HWND hwnd, LPCSTR text )
if (!text) text = "";
count = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 );
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
if ((wndPtr->text = textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
MultiByteToWideChar( CP_ACP, 0, text, -1, wndPtr->text, count );
if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
{
if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
wndPtr->text = textW;
MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count );
SERVER_START_VAR_REQ( set_window_text, (count-1) * sizeof(WCHAR) )
{
req->handle = hwnd;
memcpy( server_data_ptr(req), textW, (count-1) * sizeof(WCHAR) );
SERVER_CALL();
}
SERVER_END_VAR_REQ;
}
else
ERR("Not enough memory for window text\n");
WIN_ReleaseWndPtr( wndPtr );
WIN_ReleasePtr( wndPtr );
if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, textW );
}
......@@ -99,7 +110,16 @@ static void DEFWND_SetTextW( HWND hwnd, LPCWSTR text )
if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
strcpyW( wndPtr->text, text );
{
strcpyW( wndPtr->text, text );
SERVER_START_VAR_REQ( set_window_text, (count-1) * sizeof(WCHAR) )
{
req->handle = hwnd;
memcpy( server_data_ptr(req), wndPtr->text, (count-1) * sizeof(WCHAR) );
SERVER_CALL();
}
SERVER_END_VAR_REQ;
}
else
ERR("Not enough memory for window text\n");
text = wndPtr->text;
......
......@@ -50,10 +50,10 @@ DECLARE_DEBUG_CHANNEL(nonclient);
*/
static void add_paint_count( HWND hwnd, int incr )
{
SERVER_START_REQ( inc_queue_paint_count )
SERVER_START_REQ( inc_window_paint_count )
{
req->id = (void *)GetWindowThreadProcessId( hwnd, NULL );
req->incr = incr;
req->handle = hwnd;
req->incr = incr;
SERVER_CALL();
}
SERVER_END_REQ;
......
......@@ -187,6 +187,30 @@ static void send_parent_notify( HWND hwnd, UINT msg )
}
/*******************************************************************
* get_server_window_text
*
* Retrieve the window text from the server.
*/
static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
{
size_t len = (count - 1) * sizeof(WCHAR);
len = min( len, REQUEST_MAX_VAR_SIZE );
SERVER_START_VAR_REQ( get_window_text, len )
{
req->handle = hwnd;
if (!SERVER_CALL_ERR())
{
len = server_data_size(req);
memcpy( text, server_data_ptr(req), len );
}
else len = 0;
}
SERVER_END_VAR_REQ;
text[len / sizeof(WCHAR)] = 0;
}
/***********************************************************************
* WIN_GetPtr
*
......@@ -2240,20 +2264,41 @@ LONG WINAPI SetWindowLongW(
*/
INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
{
return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
(LPARAM)lpString );
WCHAR *buffer;
if (WIN_IsCurrentProcess( hwnd ))
return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
/* when window belongs to other process, don't send a message */
if (nMaxCount <= 0) return 0;
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
get_server_window_text( hwnd, buffer, nMaxCount );
if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
lpString[nMaxCount-1] = 0;
HeapFree( GetProcessHeap(), 0, buffer );
return strlen(lpString);
}
/*******************************************************************
* InternalGetWindowText (USER32.@)
*/
INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
{
WND *win = WIN_FindWndPtr( hwnd );
if (!win) return 0;
if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
else lpString[0] = 0;
WIN_ReleaseWndPtr( win );
WND *win;
if (nMaxCount <= 0) return 0;
if (!(win = WIN_GetPtr( hwnd ))) return 0;
if (win != WND_OTHER_PROCESS)
{
if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
else lpString[0] = 0;
WIN_ReleasePtr( win );
}
else
{
get_server_window_text( hwnd, lpString, nMaxCount );
}
return strlenW(lpString);
}
......@@ -2263,8 +2308,13 @@ INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
*/
INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
{
return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
(LPARAM)lpString );
if (WIN_IsCurrentProcess( hwnd ))
return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
/* when window belongs to other process, don't send a message */
if (nMaxCount <= 0) return 0;
get_server_window_text( hwnd, lpString, nMaxCount );
return strlenW(lpString);
}
......@@ -2274,6 +2324,12 @@ INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
*/
BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
{
if (!WIN_IsCurrentProcess( hwnd ))
{
FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
SetLastError( ERROR_ACCESS_DENIED );
return FALSE;
}
return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
}
......@@ -2283,6 +2339,12 @@ BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
*/
BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
{
if (!WIN_IsCurrentProcess( hwnd ))
{
FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
SetLastError( ERROR_ACCESS_DENIED );
return FALSE;
}
return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment