2 * Window related functions
4 * Copyright 1993, 1994, 1995, 1996, 2001, 2013-2017 Alexandre Julliard
5 * Copyright 1993 David Metcalfe
6 * Copyright 1995, 1996 Alex Korobka
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
27 #include "wine/port.h"
44 #include "wine/unicode.h"
47 #include "wine/server.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(android
);
52 /* private window data */
53 struct android_win_data
55 HWND hwnd
; /* hwnd that this private data belongs to */
56 HWND parent
; /* parent hwnd for child windows */
57 RECT window_rect
; /* USER window rectangle relative to parent */
58 RECT whole_rect
; /* X window rectangle for the whole window relative to parent */
59 RECT client_rect
; /* client area relative to parent */
60 ANativeWindow
*window
; /* native window wrapper that forwards calls to the desktop process */
61 struct window_surface
*surface
;
64 #define SWP_AGG_NOPOSCHANGE (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
66 static CRITICAL_SECTION win_data_section
;
67 static CRITICAL_SECTION_DEBUG critsect_debug
=
69 0, 0, &win_data_section
,
70 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
71 0, 0, { (DWORD_PTR
)(__FILE__
": win_data_section") }
73 static CRITICAL_SECTION win_data_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
75 static struct android_win_data
*win_data_context
[32768];
77 static inline int context_idx( HWND hwnd
)
79 return LOWORD( hwnd
) >> 1;
82 static void set_surface_region( struct window_surface
*window_surface
, HRGN win_region
);
84 /* only for use on sanitized BITMAPINFO structures */
85 static inline int get_dib_info_size( const BITMAPINFO
*info
, UINT coloruse
)
87 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
)
88 return sizeof(BITMAPINFOHEADER
) + 3 * sizeof(DWORD
);
89 if (coloruse
== DIB_PAL_COLORS
)
90 return sizeof(BITMAPINFOHEADER
) + info
->bmiHeader
.biClrUsed
* sizeof(WORD
);
91 return FIELD_OFFSET( BITMAPINFO
, bmiColors
[info
->bmiHeader
.biClrUsed
] );
94 static inline int get_dib_stride( int width
, int bpp
)
96 return ((width
* bpp
+ 31) >> 3) & ~3;
99 static inline int get_dib_image_size( const BITMAPINFO
*info
)
101 return get_dib_stride( info
->bmiHeader
.biWidth
, info
->bmiHeader
.biBitCount
)
102 * abs( info
->bmiHeader
.biHeight
);
106 /**********************************************************************
107 * get_win_monitor_dpi
109 static UINT
get_win_monitor_dpi( HWND hwnd
)
111 DPI_AWARENESS_CONTEXT context
;
114 context
= SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
);
115 ret
= GetDpiForSystem(); /* FIXME: get monitor dpi */
116 SetThreadDpiAwarenessContext( context
);
121 /***********************************************************************
124 static struct android_win_data
*alloc_win_data( HWND hwnd
)
126 struct android_win_data
*data
;
128 if ((data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
))))
131 data
->window
= create_ioctl_window( hwnd
, FALSE
,
132 (float)get_win_monitor_dpi( hwnd
) / GetDpiForWindow( hwnd
));
133 EnterCriticalSection( &win_data_section
);
134 win_data_context
[context_idx(hwnd
)] = data
;
140 /***********************************************************************
143 static void free_win_data( struct android_win_data
*data
)
145 win_data_context
[context_idx( data
->hwnd
)] = NULL
;
146 LeaveCriticalSection( &win_data_section
);
147 if (data
->window
) release_ioctl_window( data
->window
);
148 HeapFree( GetProcessHeap(), 0, data
);
152 /***********************************************************************
155 * Lock and return the data structure associated with a window.
157 static struct android_win_data
*get_win_data( HWND hwnd
)
159 struct android_win_data
*data
;
161 if (!hwnd
) return NULL
;
162 EnterCriticalSection( &win_data_section
);
163 if ((data
= win_data_context
[context_idx(hwnd
)]) && data
->hwnd
== hwnd
) return data
;
164 LeaveCriticalSection( &win_data_section
);
169 /***********************************************************************
172 * Release the data returned by get_win_data.
174 static void release_win_data( struct android_win_data
*data
)
176 if (data
) LeaveCriticalSection( &win_data_section
);
180 /***********************************************************************
183 static struct ANativeWindow
*get_ioctl_window( HWND hwnd
)
185 struct ANativeWindow
*ret
;
186 struct android_win_data
*data
= get_win_data( hwnd
);
188 if (!data
|| !data
->window
) return NULL
;
189 ret
= grab_ioctl_window( data
->window
);
190 release_win_data( data
);
195 /* Handling of events coming from the Java side */
200 union event_data data
;
203 static struct list event_queue
= LIST_INIT( event_queue
);
204 static struct java_event
*current_event
;
205 static int event_pipe
[2];
206 static DWORD desktop_tid
;
208 /***********************************************************************
211 int send_event( const union event_data
*data
)
215 if ((res
= write( event_pipe
[1], data
, sizeof(*data
) )) != sizeof(*data
))
217 p__android_log_print( ANDROID_LOG_ERROR
, "wine", "failed to send event" );
224 /***********************************************************************
227 * JNI callback, runs in the context of the Java thread.
229 void desktop_changed( JNIEnv
*env
, jobject obj
, jint width
, jint height
)
231 union event_data data
;
233 memset( &data
, 0, sizeof(data
) );
234 data
.type
= DESKTOP_CHANGED
;
235 data
.desktop
.width
= width
;
236 data
.desktop
.height
= height
;
237 p__android_log_print( ANDROID_LOG_INFO
, "wine", "desktop_changed: %ux%u", width
, height
);
242 /***********************************************************************
245 * JNI callback, runs in the context of the Java thread.
247 void config_changed( JNIEnv
*env
, jobject obj
, jint dpi
)
249 union event_data data
;
251 memset( &data
, 0, sizeof(data
) );
252 data
.type
= CONFIG_CHANGED
;
254 p__android_log_print( ANDROID_LOG_INFO
, "wine", "config_changed: %u dpi", dpi
);
259 /***********************************************************************
262 * JNI callback, runs in the context of the Java thread.
264 void surface_changed( JNIEnv
*env
, jobject obj
, jint win
, jobject surface
, jboolean client
)
266 union event_data data
;
268 memset( &data
, 0, sizeof(data
) );
269 data
.surface
.hwnd
= LongToHandle( win
);
270 data
.surface
.client
= client
;
274 ANativeWindow
*win
= pANativeWindow_fromSurface( env
, surface
);
276 if (win
->query( win
, NATIVE_WINDOW_WIDTH
, &width
) < 0) width
= 0;
277 if (win
->query( win
, NATIVE_WINDOW_HEIGHT
, &height
) < 0) height
= 0;
278 data
.surface
.window
= win
;
279 data
.surface
.width
= width
;
280 data
.surface
.height
= height
;
281 p__android_log_print( ANDROID_LOG_INFO
, "wine", "surface_changed: %p %s %ux%u",
282 data
.surface
.hwnd
, client
? "client" : "whole", width
, height
);
284 data
.type
= SURFACE_CHANGED
;
289 /***********************************************************************
292 * JNI callback, runs in the context of the Java thread.
294 jboolean
motion_event( JNIEnv
*env
, jobject obj
, jint win
, jint action
, jint x
, jint y
, jint state
, jint vscroll
)
296 static LONG button_state
;
297 union event_data data
;
300 int mask
= action
& AMOTION_EVENT_ACTION_MASK
;
302 if (!( mask
== AMOTION_EVENT_ACTION_DOWN
||
303 mask
== AMOTION_EVENT_ACTION_UP
||
304 mask
== AMOTION_EVENT_ACTION_CANCEL
||
305 mask
== AMOTION_EVENT_ACTION_SCROLL
||
306 mask
== AMOTION_EVENT_ACTION_MOVE
||
307 mask
== AMOTION_EVENT_ACTION_HOVER_MOVE
||
308 mask
== AMOTION_EVENT_ACTION_BUTTON_PRESS
||
309 mask
== AMOTION_EVENT_ACTION_BUTTON_RELEASE
))
312 /* make sure a subsequent AMOTION_EVENT_ACTION_UP is not treated as a touch event */
313 if (mask
== AMOTION_EVENT_ACTION_BUTTON_RELEASE
) state
|= 0x80000000;
315 prev_state
= InterlockedExchange( &button_state
, state
);
317 data
.type
= MOTION_EVENT
;
318 data
.motion
.hwnd
= LongToHandle( win
);
319 data
.motion
.input
.type
= INPUT_MOUSE
;
320 data
.motion
.input
.u
.mi
.dx
= x
;
321 data
.motion
.input
.u
.mi
.dy
= y
;
322 data
.motion
.input
.u
.mi
.mouseData
= 0;
323 data
.motion
.input
.u
.mi
.time
= 0;
324 data
.motion
.input
.u
.mi
.dwExtraInfo
= 0;
325 data
.motion
.input
.u
.mi
.dwFlags
= MOUSEEVENTF_MOVE
| MOUSEEVENTF_ABSOLUTE
;
326 switch (action
& AMOTION_EVENT_ACTION_MASK
)
328 case AMOTION_EVENT_ACTION_DOWN
:
329 case AMOTION_EVENT_ACTION_BUTTON_PRESS
:
330 if ((state
& ~prev_state
) & AMOTION_EVENT_BUTTON_PRIMARY
)
331 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTDOWN
;
332 if ((state
& ~prev_state
) & AMOTION_EVENT_BUTTON_SECONDARY
)
333 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_RIGHTDOWN
;
334 if ((state
& ~prev_state
) & AMOTION_EVENT_BUTTON_TERTIARY
)
335 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_MIDDLEDOWN
;
336 if (!(state
& ~prev_state
)) /* touch event */
337 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTDOWN
;
339 case AMOTION_EVENT_ACTION_UP
:
340 case AMOTION_EVENT_ACTION_CANCEL
:
341 case AMOTION_EVENT_ACTION_BUTTON_RELEASE
:
342 if ((prev_state
& ~state
) & AMOTION_EVENT_BUTTON_PRIMARY
)
343 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTUP
;
344 if ((prev_state
& ~state
) & AMOTION_EVENT_BUTTON_SECONDARY
)
345 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_RIGHTUP
;
346 if ((prev_state
& ~state
) & AMOTION_EVENT_BUTTON_TERTIARY
)
347 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_MIDDLEUP
;
348 if (!(prev_state
& ~state
)) /* touch event */
349 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTUP
;
351 case AMOTION_EVENT_ACTION_SCROLL
:
352 data
.motion
.input
.u
.mi
.dwFlags
|= MOUSEEVENTF_WHEEL
;
353 data
.motion
.input
.u
.mi
.mouseData
= vscroll
< 0 ? -WHEEL_DELTA
: WHEEL_DELTA
;
355 case AMOTION_EVENT_ACTION_MOVE
:
356 case AMOTION_EVENT_ACTION_HOVER_MOVE
:
366 /***********************************************************************
369 static void init_event_queue(void)
374 if (pipe2( event_pipe
, O_CLOEXEC
| O_NONBLOCK
) == -1)
376 ERR( "could not create data\n" );
379 if (wine_server_fd_to_handle( event_pipe
[0], GENERIC_READ
| SYNCHRONIZE
, 0, &handle
))
381 ERR( "Can't allocate handle for event fd\n" );
384 SERVER_START_REQ( set_queue_fd
)
386 req
->handle
= wine_server_obj_handle( handle
);
387 ret
= wine_server_call( req
);
392 ERR( "Can't store handle for event fd %x\n", ret
);
395 CloseHandle( handle
);
396 desktop_tid
= GetCurrentThreadId();
400 /***********************************************************************
403 * Pull events from the event pipe and add them to the queue
405 static void pull_events(void)
407 struct java_event
*event
;
412 if (!(event
= HeapAlloc( GetProcessHeap(), 0, sizeof(*event
) ))) break;
414 res
= read( event_pipe
[0], &event
->data
, sizeof(event
->data
) );
415 if (res
!= sizeof(event
->data
)) break;
416 list_add_tail( &event_queue
, &event
->entry
);
418 HeapFree( GetProcessHeap(), 0, event
);
422 /***********************************************************************
425 static int process_events( DWORD mask
)
427 DPI_AWARENESS_CONTEXT context
;
428 struct java_event
*event
, *next
, *previous
;
429 unsigned int count
= 0;
431 assert( GetCurrentThreadId() == desktop_tid
);
435 previous
= current_event
;
437 LIST_FOR_EACH_ENTRY_SAFE( event
, next
, &event_queue
, struct java_event
, entry
)
439 switch (event
->data
.type
)
441 case SURFACE_CHANGED
:
442 break; /* always process it to unblock other threads */
444 if (event
->data
.motion
.input
.u
.mi
.dwFlags
& (MOUSEEVENTF_LEFTDOWN
|MOUSEEVENTF_RIGHTDOWN
|
445 MOUSEEVENTF_MIDDLEDOWN
|MOUSEEVENTF_LEFTUP
|
446 MOUSEEVENTF_RIGHTUP
|MOUSEEVENTF_MIDDLEUP
))
448 if (mask
& QS_MOUSEBUTTON
) break;
450 else if (mask
& QS_MOUSEMOVE
) break;
451 continue; /* skip it */
453 if (mask
& QS_KEY
) break;
454 continue; /* skip it */
456 if (mask
& QS_SENDMESSAGE
) break;
457 continue; /* skip it */
460 /* remove it first, in case we process events recursively */
461 list_remove( &event
->entry
);
462 current_event
= event
;
464 switch (event
->data
.type
)
466 case DESKTOP_CHANGED
:
467 TRACE( "DESKTOP_CHANGED %ux%u\n", event
->data
.desktop
.width
, event
->data
.desktop
.height
);
468 context
= SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE
);
469 screen_width
= event
->data
.desktop
.width
;
470 screen_height
= event
->data
.desktop
.height
;
471 init_monitors( screen_width
, screen_height
);
472 SetWindowPos( GetDesktopWindow(), 0, 0, 0, screen_width
, screen_height
,
473 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
474 SetThreadDpiAwarenessContext( context
);
478 TRACE( "CONFIG_CHANGED dpi %u\n", event
->data
.cfg
.dpi
);
479 set_screen_dpi( event
->data
.cfg
.dpi
);
482 case SURFACE_CHANGED
:
483 TRACE("SURFACE_CHANGED %p %p %s size %ux%u\n", event
->data
.surface
.hwnd
,
484 event
->data
.surface
.window
, event
->data
.surface
.client
? "client" : "whole",
485 event
->data
.surface
.width
, event
->data
.surface
.height
);
487 register_native_window( event
->data
.surface
.hwnd
, event
->data
.surface
.window
, event
->data
.surface
.client
);
492 HWND capture
= get_capture_window();
494 if (event
->data
.motion
.input
.u
.mi
.dwFlags
& (MOUSEEVENTF_LEFTDOWN
|MOUSEEVENTF_RIGHTDOWN
|MOUSEEVENTF_MIDDLEDOWN
))
495 TRACE( "BUTTONDOWN pos %d,%d hwnd %p flags %x\n",
496 event
->data
.motion
.input
.u
.mi
.dx
, event
->data
.motion
.input
.u
.mi
.dy
,
497 event
->data
.motion
.hwnd
, event
->data
.motion
.input
.u
.mi
.dwFlags
);
498 else if (event
->data
.motion
.input
.u
.mi
.dwFlags
& (MOUSEEVENTF_LEFTUP
|MOUSEEVENTF_RIGHTUP
|MOUSEEVENTF_MIDDLEUP
))
499 TRACE( "BUTTONUP pos %d,%d hwnd %p flags %x\n",
500 event
->data
.motion
.input
.u
.mi
.dx
, event
->data
.motion
.input
.u
.mi
.dy
,
501 event
->data
.motion
.hwnd
, event
->data
.motion
.input
.u
.mi
.dwFlags
);
503 TRACE( "MOUSEMOVE pos %d,%d hwnd %p flags %x\n",
504 event
->data
.motion
.input
.u
.mi
.dx
, event
->data
.motion
.input
.u
.mi
.dy
,
505 event
->data
.motion
.hwnd
, event
->data
.motion
.input
.u
.mi
.dwFlags
);
506 if (!capture
&& (event
->data
.motion
.input
.u
.mi
.dwFlags
& MOUSEEVENTF_ABSOLUTE
))
509 SetRect( &rect
, event
->data
.motion
.input
.u
.mi
.dx
, event
->data
.motion
.input
.u
.mi
.dy
,
510 event
->data
.motion
.input
.u
.mi
.dx
+ 1, event
->data
.motion
.input
.u
.mi
.dy
+ 1 );
512 SERVER_START_REQ( update_window_zorder
)
514 req
->window
= wine_server_user_handle( event
->data
.motion
.hwnd
);
515 req
->rect
.left
= rect
.left
;
516 req
->rect
.top
= rect
.top
;
517 req
->rect
.right
= rect
.right
;
518 req
->rect
.bottom
= rect
.bottom
;
519 wine_server_call( req
);
523 __wine_send_input( capture
? capture
: event
->data
.motion
.hwnd
, &event
->data
.motion
.input
);
528 if (event
->data
.kbd
.input
.u
.ki
.dwFlags
& KEYEVENTF_KEYUP
)
529 TRACE("KEYUP hwnd %p vkey %x '%c' scancode %x\n", event
->data
.kbd
.hwnd
,
530 event
->data
.kbd
.input
.u
.ki
.wVk
, event
->data
.kbd
.input
.u
.ki
.wVk
,
531 event
->data
.kbd
.input
.u
.ki
.wScan
);
533 TRACE("KEYDOWN hwnd %p vkey %x '%c' scancode %x\n", event
->data
.kbd
.hwnd
,
534 event
->data
.kbd
.input
.u
.ki
.wVk
, event
->data
.kbd
.input
.u
.ki
.wVk
,
535 event
->data
.kbd
.input
.u
.ki
.wScan
);
536 update_keyboard_lock_state( event
->data
.kbd
.input
.u
.ki
.wVk
, event
->data
.kbd
.lock_state
);
537 __wine_send_input( 0, &event
->data
.kbd
.input
);
541 FIXME( "got event %u\n", event
->data
.type
);
543 HeapFree( GetProcessHeap(), 0, event
);
545 /* next may have been removed by a recursive call, so reset it to the beginning of the list */
546 next
= LIST_ENTRY( event_queue
.next
, struct java_event
, entry
);
548 current_event
= previous
;
553 /***********************************************************************
556 static int wait_events( int timeout
)
558 assert( GetCurrentThreadId() == desktop_tid
);
562 struct pollfd pollfd
;
565 pollfd
.fd
= event_pipe
[0];
566 pollfd
.events
= POLLIN
| POLLHUP
;
567 ret
= poll( &pollfd
, 1, timeout
);
568 if (ret
== -1 && errno
== EINTR
) continue;
569 if (ret
&& (pollfd
.revents
& (POLLHUP
| POLLERR
))) ret
= -1;
575 /* Window surface support */
577 struct android_window_surface
579 struct window_surface header
;
581 ANativeWindow
*window
;
584 RGNDATA
*region_data
;
589 CRITICAL_SECTION crit
;
590 BITMAPINFO info
; /* variable size, must be last */
593 static struct android_window_surface
*get_android_surface( struct window_surface
*surface
)
595 return (struct android_window_surface
*)surface
;
598 static inline void reset_bounds( RECT
*bounds
)
600 bounds
->left
= bounds
->top
= INT_MAX
;
601 bounds
->right
= bounds
->bottom
= INT_MIN
;
604 static inline void add_bounds_rect( RECT
*bounds
, const RECT
*rect
)
606 if (rect
->left
>= rect
->right
|| rect
->top
>= rect
->bottom
) return;
607 bounds
->left
= min( bounds
->left
, rect
->left
);
608 bounds
->top
= min( bounds
->top
, rect
->top
);
609 bounds
->right
= max( bounds
->right
, rect
->right
);
610 bounds
->bottom
= max( bounds
->bottom
, rect
->bottom
);
613 /* store the palette or color mask data in the bitmap info structure */
614 static void set_color_info( BITMAPINFO
*info
, BOOL has_alpha
)
616 DWORD
*colors
= (DWORD
*)info
->bmiColors
;
618 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
619 info
->bmiHeader
.biClrUsed
= 0;
620 info
->bmiHeader
.biBitCount
= 32;
623 info
->bmiHeader
.biCompression
= BI_RGB
;
626 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
627 colors
[0] = 0xff0000;
628 colors
[1] = 0x00ff00;
629 colors
[2] = 0x0000ff;
632 /* apply the window region to a single line of the destination image. */
633 static void apply_line_region( DWORD
*dst
, int width
, int x
, int y
, const RECT
*rect
, const RECT
*end
)
635 while (rect
< end
&& rect
->top
<= y
&& width
> 0)
639 memset( dst
, 0, min( rect
->left
- x
, width
) * sizeof(*dst
) );
640 dst
+= rect
->left
- x
;
641 width
-= rect
->left
- x
;
646 dst
+= rect
->right
- x
;
647 width
-= rect
->right
- x
;
652 if (width
> 0) memset( dst
, 0, width
* sizeof(*dst
) );
655 /***********************************************************************
656 * android_surface_lock
658 static void android_surface_lock( struct window_surface
*window_surface
)
660 struct android_window_surface
*surface
= get_android_surface( window_surface
);
662 EnterCriticalSection( &surface
->crit
);
665 /***********************************************************************
666 * android_surface_unlock
668 static void android_surface_unlock( struct window_surface
*window_surface
)
670 struct android_window_surface
*surface
= get_android_surface( window_surface
);
672 LeaveCriticalSection( &surface
->crit
);
675 /***********************************************************************
676 * android_surface_get_bitmap_info
678 static void *android_surface_get_bitmap_info( struct window_surface
*window_surface
, BITMAPINFO
*info
)
680 struct android_window_surface
*surface
= get_android_surface( window_surface
);
682 memcpy( info
, &surface
->info
, get_dib_info_size( &surface
->info
, DIB_RGB_COLORS
));
683 return surface
->bits
;
686 /***********************************************************************
687 * android_surface_get_bounds
689 static RECT
*android_surface_get_bounds( struct window_surface
*window_surface
)
691 struct android_window_surface
*surface
= get_android_surface( window_surface
);
693 return &surface
->bounds
;
696 /***********************************************************************
697 * android_surface_set_region
699 static void android_surface_set_region( struct window_surface
*window_surface
, HRGN region
)
701 struct android_window_surface
*surface
= get_android_surface( window_surface
);
703 TRACE( "updating surface %p hwnd %p with %p\n", surface
, surface
->hwnd
, region
);
705 window_surface
->funcs
->lock( window_surface
);
708 if (surface
->region
) DeleteObject( surface
->region
);
713 if (!surface
->region
) surface
->region
= CreateRectRgn( 0, 0, 0, 0 );
714 CombineRgn( surface
->region
, region
, 0, RGN_COPY
);
716 window_surface
->funcs
->unlock( window_surface
);
717 set_surface_region( &surface
->header
, (HRGN
)1 );
720 /***********************************************************************
721 * android_surface_flush
723 static void android_surface_flush( struct window_surface
*window_surface
)
725 struct android_window_surface
*surface
= get_android_surface( window_surface
);
726 ANativeWindow_Buffer buffer
;
731 window_surface
->funcs
->lock( window_surface
);
732 SetRect( &rect
, 0, 0, surface
->header
.rect
.right
- surface
->header
.rect
.left
,
733 surface
->header
.rect
.bottom
- surface
->header
.rect
.top
);
734 needs_flush
= IntersectRect( &rect
, &rect
, &surface
->bounds
);
735 reset_bounds( &surface
->bounds
);
736 window_surface
->funcs
->unlock( window_surface
);
737 if (!needs_flush
) return;
739 TRACE( "flushing %p hwnd %p surface %s rect %s bits %p alpha %02x key %08x region %u rects\n",
740 surface
, surface
->hwnd
, wine_dbgstr_rect( &surface
->header
.rect
),
741 wine_dbgstr_rect( &rect
), surface
->bits
, surface
->alpha
, surface
->color_key
,
742 surface
->region_data
? surface
->region_data
->rdh
.nCount
: 0 );
746 rc
.right
= rect
.right
;
747 rc
.bottom
= rect
.bottom
;
749 if (!surface
->window
->perform( surface
->window
, NATIVE_WINDOW_LOCK
, &buffer
, &rc
))
751 const RECT
*rgn_rect
= NULL
, *end
= NULL
;
752 unsigned int *src
, *dst
;
757 rect
.right
= rc
.right
;
758 rect
.bottom
= rc
.bottom
;
759 IntersectRect( &rect
, &rect
, &surface
->header
.rect
);
761 if (surface
->region_data
)
763 rgn_rect
= (RECT
*)surface
->region_data
->Buffer
;
764 end
= rgn_rect
+ surface
->region_data
->rdh
.nCount
;
766 src
= (unsigned int *)surface
->bits
767 + (rect
.top
- surface
->header
.rect
.top
) * surface
->info
.bmiHeader
.biWidth
768 + (rect
.left
- surface
->header
.rect
.left
);
769 dst
= (unsigned int *)buffer
.bits
+ rect
.top
* buffer
.stride
+ rect
.left
;
770 width
= min( rect
.right
- rect
.left
, buffer
.stride
);
772 for (y
= rect
.top
; y
< min( buffer
.height
, rect
.bottom
); y
++)
774 if (surface
->info
.bmiHeader
.biCompression
== BI_RGB
)
775 memcpy( dst
, src
, width
* sizeof(*dst
) );
776 else if (surface
->alpha
== 255)
777 for (x
= 0; x
< width
; x
++) dst
[x
] = src
[x
] | 0xff000000;
779 for (x
= 0; x
< width
; x
++)
780 dst
[x
] = ((surface
->alpha
<< 24) |
781 (((BYTE
)(src
[x
] >> 16) * surface
->alpha
/ 255) << 16) |
782 (((BYTE
)(src
[x
] >> 8) * surface
->alpha
/ 255) << 8) |
783 (((BYTE
)src
[x
] * surface
->alpha
/ 255)));
785 if (surface
->color_key
!= CLR_INVALID
)
786 for (x
= 0; x
< width
; x
++) if ((src
[x
] & 0xffffff) == surface
->color_key
) dst
[x
] = 0;
790 while (rgn_rect
< end
&& rgn_rect
->bottom
<= y
) rgn_rect
++;
791 apply_line_region( dst
, width
, rect
.left
, y
, rgn_rect
, end
);
794 src
+= surface
->info
.bmiHeader
.biWidth
;
795 dst
+= buffer
.stride
;
797 surface
->window
->perform( surface
->window
, NATIVE_WINDOW_UNLOCK_AND_POST
);
799 else TRACE( "Unable to lock surface %p window %p buffer %p\n",
800 surface
, surface
->hwnd
, surface
->window
);
803 /***********************************************************************
804 * android_surface_destroy
806 static void android_surface_destroy( struct window_surface
*window_surface
)
808 struct android_window_surface
*surface
= get_android_surface( window_surface
);
810 TRACE( "freeing %p bits %p\n", surface
, surface
->bits
);
812 surface
->crit
.DebugInfo
->Spare
[0] = 0;
813 DeleteCriticalSection( &surface
->crit
);
814 HeapFree( GetProcessHeap(), 0, surface
->region_data
);
815 if (surface
->region
) DeleteObject( surface
->region
);
816 release_ioctl_window( surface
->window
);
817 HeapFree( GetProcessHeap(), 0, surface
->bits
);
818 HeapFree( GetProcessHeap(), 0, surface
);
821 static const struct window_surface_funcs android_surface_funcs
=
823 android_surface_lock
,
824 android_surface_unlock
,
825 android_surface_get_bitmap_info
,
826 android_surface_get_bounds
,
827 android_surface_set_region
,
828 android_surface_flush
,
829 android_surface_destroy
832 static BOOL
is_argb_surface( struct window_surface
*surface
)
834 return surface
&& surface
->funcs
== &android_surface_funcs
&&
835 get_android_surface( surface
)->info
.bmiHeader
.biCompression
== BI_RGB
;
838 /***********************************************************************
841 static void set_color_key( struct android_window_surface
*surface
, COLORREF key
)
843 if (key
== CLR_INVALID
)
844 surface
->color_key
= CLR_INVALID
;
845 else if (surface
->info
.bmiHeader
.biBitCount
<= 8)
846 surface
->color_key
= CLR_INVALID
;
847 else if (key
& (1 << 24)) /* PALETTEINDEX */
848 surface
->color_key
= 0;
849 else if (key
>> 16 == 0x10ff) /* DIBINDEX */
850 surface
->color_key
= 0;
851 else if (surface
->info
.bmiHeader
.biBitCount
== 24)
852 surface
->color_key
= key
;
854 surface
->color_key
= (GetRValue(key
) << 16) | (GetGValue(key
) << 8) | GetBValue(key
);
857 /***********************************************************************
860 static void set_surface_region( struct window_surface
*window_surface
, HRGN win_region
)
862 struct android_window_surface
*surface
= get_android_surface( window_surface
);
863 struct android_win_data
*win_data
;
864 HRGN region
= win_region
;
865 RGNDATA
*data
= NULL
;
867 int offset_x
, offset_y
;
869 if (window_surface
->funcs
!= &android_surface_funcs
) return; /* we may get the null surface */
871 if (!(win_data
= get_win_data( surface
->hwnd
))) return;
872 offset_x
= win_data
->window_rect
.left
- win_data
->whole_rect
.left
;
873 offset_y
= win_data
->window_rect
.top
- win_data
->whole_rect
.top
;
874 release_win_data( win_data
);
876 if (win_region
== (HRGN
)1) /* hack: win_region == 1 means retrieve region from server */
878 region
= CreateRectRgn( 0, 0, win_data
->window_rect
.right
- win_data
->window_rect
.left
,
879 win_data
->window_rect
.bottom
- win_data
->window_rect
.top
);
880 if (GetWindowRgn( surface
->hwnd
, region
) == ERROR
&& !surface
->region
) goto done
;
883 OffsetRgn( region
, offset_x
, offset_y
);
884 if (surface
->region
) CombineRgn( region
, region
, surface
->region
, RGN_AND
);
886 if (!(size
= GetRegionData( region
, 0, NULL
))) goto done
;
887 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
889 if (!GetRegionData( region
, size
, data
))
891 HeapFree( GetProcessHeap(), 0, data
);
896 window_surface
->funcs
->lock( window_surface
);
897 HeapFree( GetProcessHeap(), 0, surface
->region_data
);
898 surface
->region_data
= data
;
899 *window_surface
->funcs
->get_bounds( window_surface
) = surface
->header
.rect
;
900 window_surface
->funcs
->unlock( window_surface
);
901 if (region
!= win_region
) DeleteObject( region
);
904 /***********************************************************************
907 static struct window_surface
*create_surface( HWND hwnd
, const RECT
*rect
,
908 BYTE alpha
, COLORREF color_key
, BOOL src_alpha
)
910 struct android_window_surface
*surface
;
911 int width
= rect
->right
- rect
->left
, height
= rect
->bottom
- rect
->top
;
913 surface
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
914 FIELD_OFFSET( struct android_window_surface
, info
.bmiColors
[3] ));
915 if (!surface
) return NULL
;
916 set_color_info( &surface
->info
, src_alpha
);
917 surface
->info
.bmiHeader
.biWidth
= width
;
918 surface
->info
.bmiHeader
.biHeight
= -height
; /* top-down */
919 surface
->info
.bmiHeader
.biPlanes
= 1;
920 surface
->info
.bmiHeader
.biSizeImage
= get_dib_image_size( &surface
->info
);
922 InitializeCriticalSection( &surface
->crit
);
923 surface
->crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": surface");
925 surface
->header
.funcs
= &android_surface_funcs
;
926 surface
->header
.rect
= *rect
;
927 surface
->header
.ref
= 1;
928 surface
->hwnd
= hwnd
;
929 surface
->window
= get_ioctl_window( hwnd
);
930 surface
->alpha
= alpha
;
931 set_color_key( surface
, color_key
);
932 set_surface_region( &surface
->header
, (HRGN
)1 );
933 reset_bounds( &surface
->bounds
);
935 if (!(surface
->bits
= HeapAlloc( GetProcessHeap(), 0, surface
->info
.bmiHeader
.biSizeImage
)))
938 TRACE( "created %p hwnd %p %s bits %p-%p\n", surface
, hwnd
, wine_dbgstr_rect(rect
),
939 surface
->bits
, (char *)surface
->bits
+ surface
->info
.bmiHeader
.biSizeImage
);
941 return &surface
->header
;
944 android_surface_destroy( &surface
->header
);
948 /***********************************************************************
949 * set_surface_layered
951 static void set_surface_layered( struct window_surface
*window_surface
, BYTE alpha
, COLORREF color_key
)
953 struct android_window_surface
*surface
= get_android_surface( window_surface
);
957 if (window_surface
->funcs
!= &android_surface_funcs
) return; /* we may get the null surface */
959 window_surface
->funcs
->lock( window_surface
);
960 prev_key
= surface
->color_key
;
961 prev_alpha
= surface
->alpha
;
962 surface
->alpha
= alpha
;
963 set_color_key( surface
, color_key
);
964 if (alpha
!= prev_alpha
|| surface
->color_key
!= prev_key
) /* refresh */
965 *window_surface
->funcs
->get_bounds( window_surface
) = surface
->header
.rect
;
966 window_surface
->funcs
->unlock( window_surface
);
970 static WNDPROC desktop_orig_wndproc
;
972 static LRESULT CALLBACK
desktop_wndproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
976 case WM_PARENTNOTIFY
:
977 if (LOWORD(wp
) == WM_DESTROY
) destroy_ioctl_window( (HWND
)lp
, FALSE
);
980 return desktop_orig_wndproc( hwnd
, msg
, wp
, lp
);
984 /***********************************************************************
985 * ANDROID_MsgWaitForMultipleObjectsEx
987 DWORD CDECL
ANDROID_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
,
988 DWORD timeout
, DWORD mask
, DWORD flags
)
990 if (GetCurrentThreadId() == desktop_tid
)
992 /* don't process nested events */
993 if (current_event
) mask
= 0;
994 if (process_events( mask
)) return count
- 1;
996 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
997 timeout
, flags
& MWMO_ALERTABLE
);
1000 /**********************************************************************
1001 * ANDROID_CreateWindow
1003 BOOL CDECL
ANDROID_CreateWindow( HWND hwnd
)
1005 TRACE( "%p\n", hwnd
);
1007 if (hwnd
== GetDesktopWindow())
1009 struct android_win_data
*data
;
1012 start_android_device();
1013 if (!(data
= alloc_win_data( hwnd
))) return FALSE
;
1014 release_win_data( data
);
1020 /***********************************************************************
1021 * ANDROID_DestroyWindow
1023 void CDECL
ANDROID_DestroyWindow( HWND hwnd
)
1025 struct android_win_data
*data
;
1027 if (!(data
= get_win_data( hwnd
))) return;
1029 if (data
->surface
) window_surface_release( data
->surface
);
1030 data
->surface
= NULL
;
1031 destroy_gl_drawable( hwnd
);
1032 free_win_data( data
);
1036 /***********************************************************************
1039 * Create a data window structure for an existing window.
1041 static struct android_win_data
*create_win_data( HWND hwnd
, const RECT
*window_rect
,
1042 const RECT
*client_rect
)
1044 struct android_win_data
*data
;
1047 if (!(parent
= GetAncestor( hwnd
, GA_PARENT
))) return NULL
; /* desktop or HWND_MESSAGE */
1049 if (!(data
= alloc_win_data( hwnd
))) return NULL
;
1051 data
->parent
= (parent
== GetDesktopWindow()) ? 0 : parent
;
1052 data
->whole_rect
= data
->window_rect
= *window_rect
;
1053 data
->client_rect
= *client_rect
;
1058 static inline BOOL
get_surface_rect( const RECT
*visible_rect
, RECT
*surface_rect
)
1060 if (!IntersectRect( surface_rect
, visible_rect
, &virtual_screen_rect
)) return FALSE
;
1061 OffsetRect( surface_rect
, -visible_rect
->left
, -visible_rect
->top
);
1062 surface_rect
->left
&= ~31;
1063 surface_rect
->top
&= ~31;
1064 surface_rect
->right
= max( surface_rect
->left
+ 32, (surface_rect
->right
+ 31) & ~31 );
1065 surface_rect
->bottom
= max( surface_rect
->top
+ 32, (surface_rect
->bottom
+ 31) & ~31 );
1070 /***********************************************************************
1071 * ANDROID_WindowPosChanging
1073 void CDECL
ANDROID_WindowPosChanging( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
1074 const RECT
*window_rect
, const RECT
*client_rect
, RECT
*visible_rect
,
1075 struct window_surface
**surface
)
1077 struct android_win_data
*data
= get_win_data( hwnd
);
1082 BOOL layered
= GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_LAYERED
;
1084 TRACE( "win %p window %s client %s style %08x flags %08x\n",
1085 hwnd
, wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
),
1086 GetWindowLongW( hwnd
, GWL_STYLE
), swp_flags
);
1088 if (!data
&& !(data
= create_win_data( hwnd
, window_rect
, client_rect
))) return;
1090 *visible_rect
= *window_rect
;
1092 /* create the window surface if necessary */
1094 if (data
->parent
) goto done
;
1095 if (swp_flags
& SWP_HIDEWINDOW
) goto done
;
1096 if (is_argb_surface( data
->surface
)) goto done
;
1097 if (!get_surface_rect( visible_rect
, &surface_rect
)) goto done
;
1101 if (!memcmp( &data
->surface
->rect
, &surface_rect
, sizeof(surface_rect
) ))
1103 /* existing surface is good enough */
1104 window_surface_add_ref( data
->surface
);
1105 if (*surface
) window_surface_release( *surface
);
1106 *surface
= data
->surface
;
1110 if (!(swp_flags
& SWP_SHOWWINDOW
) && !(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
)) goto done
;
1112 if (!layered
|| !GetLayeredWindowAttributes( hwnd
, &key
, &alpha
, &flags
)) flags
= 0;
1113 if (!(flags
& LWA_ALPHA
)) alpha
= 255;
1114 if (!(flags
& LWA_COLORKEY
)) key
= CLR_INVALID
;
1116 if (*surface
) window_surface_release( *surface
);
1117 *surface
= create_surface( data
->hwnd
, &surface_rect
, alpha
, key
, FALSE
);
1120 release_win_data( data
);
1124 /***********************************************************************
1125 * ANDROID_WindowPosChanged
1127 void CDECL
ANDROID_WindowPosChanged( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
1128 const RECT
*window_rect
, const RECT
*client_rect
,
1129 const RECT
*visible_rect
, const RECT
*valid_rects
,
1130 struct window_surface
*surface
)
1132 struct android_win_data
*data
;
1133 DWORD new_style
= GetWindowLongW( hwnd
, GWL_STYLE
);
1136 if (!(data
= get_win_data( hwnd
))) return;
1138 data
->window_rect
= *window_rect
;
1139 data
->whole_rect
= *visible_rect
;
1140 data
->client_rect
= *client_rect
;
1142 if (!is_argb_surface( data
->surface
))
1144 if (surface
) window_surface_add_ref( surface
);
1145 if (data
->surface
) window_surface_release( data
->surface
);
1146 data
->surface
= surface
;
1148 if (!data
->parent
) owner
= GetWindow( hwnd
, GW_OWNER
);
1149 release_win_data( data
);
1151 if (!(swp_flags
& SWP_NOZORDER
)) insert_after
= GetWindow( hwnd
, GW_HWNDPREV
);
1153 TRACE( "win %p window %s client %s style %08x owner %p after %p flags %08x\n", hwnd
,
1154 wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
),
1155 new_style
, owner
, insert_after
, swp_flags
);
1157 ioctl_window_pos_changed( hwnd
, window_rect
, client_rect
, visible_rect
,
1158 new_style
, swp_flags
, insert_after
, owner
);
1162 /***********************************************************************
1163 * ANDROID_ShowWindow
1165 UINT CDECL
ANDROID_ShowWindow( HWND hwnd
, INT cmd
, RECT
*rect
, UINT swp
)
1167 if (IsRectEmpty( rect
)) return swp
;
1168 if (!IsIconic( hwnd
)) return swp
;
1169 /* always hide icons off-screen */
1170 if (rect
->left
!= -32000 || rect
->top
!= -32000)
1172 OffsetRect( rect
, -32000 - rect
->left
, -32000 - rect
->top
);
1173 swp
&= ~(SWP_NOMOVE
| SWP_NOCLIENTMOVE
);
1179 /*****************************************************************
1182 void CDECL
ANDROID_SetParent( HWND hwnd
, HWND parent
, HWND old_parent
)
1184 struct android_win_data
*data
;
1186 if (parent
== old_parent
) return;
1187 if (!(data
= get_win_data( hwnd
))) return;
1189 TRACE( "win %p parent %p -> %p\n", hwnd
, old_parent
, parent
);
1191 data
->parent
= (parent
== GetDesktopWindow()) ? 0 : parent
;
1192 ioctl_set_window_parent( hwnd
, parent
, (float)get_win_monitor_dpi( hwnd
) / GetDpiForWindow( hwnd
));
1193 release_win_data( data
);
1197 /***********************************************************************
1198 * ANDROID_SetCapture
1200 void CDECL
ANDROID_SetCapture( HWND hwnd
, UINT flags
)
1202 if (!(flags
& (GUI_INMOVESIZE
| GUI_INMENUMODE
))) return;
1203 ioctl_set_capture( hwnd
);
1207 /***********************************************************************
1208 * ANDROID_SetWindowStyle
1210 void CDECL
ANDROID_SetWindowStyle( HWND hwnd
, INT offset
, STYLESTRUCT
*style
)
1212 struct android_win_data
*data
;
1213 DWORD changed
= style
->styleNew
^ style
->styleOld
;
1215 if (hwnd
== GetDesktopWindow()) return;
1216 if (!(data
= get_win_data( hwnd
))) return;
1218 if (offset
== GWL_EXSTYLE
&& (changed
& WS_EX_LAYERED
)) /* changing WS_EX_LAYERED resets attributes */
1220 if (is_argb_surface( data
->surface
))
1222 if (data
->surface
) window_surface_release( data
->surface
);
1223 data
->surface
= NULL
;
1225 else if (data
->surface
) set_surface_layered( data
->surface
, 255, CLR_INVALID
);
1227 release_win_data( data
);
1231 /***********************************************************************
1232 * ANDROID_SetWindowRgn
1234 void CDECL
ANDROID_SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL redraw
)
1236 struct android_win_data
*data
;
1238 if ((data
= get_win_data( hwnd
)))
1240 if (data
->surface
) set_surface_region( data
->surface
, hrgn
);
1241 release_win_data( data
);
1243 else FIXME( "not supported on other process window %p\n", hwnd
);
1247 /***********************************************************************
1248 * ANDROID_SetLayeredWindowAttributes
1250 void CDECL
ANDROID_SetLayeredWindowAttributes( HWND hwnd
, COLORREF key
, BYTE alpha
, DWORD flags
)
1252 struct android_win_data
*data
;
1254 if (!(flags
& LWA_ALPHA
)) alpha
= 255;
1255 if (!(flags
& LWA_COLORKEY
)) key
= CLR_INVALID
;
1257 if ((data
= get_win_data( hwnd
)))
1259 if (data
->surface
) set_surface_layered( data
->surface
, alpha
, key
);
1260 release_win_data( data
);
1265 /*****************************************************************************
1266 * ANDROID_UpdateLayeredWindow
1268 BOOL CDECL
ANDROID_UpdateLayeredWindow( HWND hwnd
, const UPDATELAYEREDWINDOWINFO
*info
,
1269 const RECT
*window_rect
)
1271 struct window_surface
*surface
;
1272 struct android_win_data
*data
;
1273 BLENDFUNCTION blend
= { AC_SRC_OVER
, 0, 255, 0 };
1274 COLORREF color_key
= (info
->dwFlags
& ULW_COLORKEY
) ? info
->crKey
: CLR_INVALID
;
1275 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1276 BITMAPINFO
*bmi
= (BITMAPINFO
*)buffer
;
1277 void *src_bits
, *dst_bits
;
1278 RECT rect
, src_rect
;
1283 if (!(data
= get_win_data( hwnd
))) return FALSE
;
1285 rect
= *window_rect
;
1286 OffsetRect( &rect
, -window_rect
->left
, -window_rect
->top
);
1288 surface
= data
->surface
;
1289 if (!is_argb_surface( surface
))
1291 if (surface
) window_surface_release( surface
);
1295 if (!surface
|| !EqualRect( &surface
->rect
, &rect
))
1297 data
->surface
= create_surface( data
->hwnd
, &rect
, 255, color_key
, TRUE
);
1298 if (surface
) window_surface_release( surface
);
1299 surface
= data
->surface
;
1301 else set_surface_layered( surface
, 255, color_key
);
1303 if (surface
) window_surface_add_ref( surface
);
1304 release_win_data( data
);
1306 if (!surface
) return FALSE
;
1309 window_surface_release( surface
);
1313 dst_bits
= surface
->funcs
->get_info( surface
, bmi
);
1315 if (!(dib
= CreateDIBSection( info
->hdcDst
, bmi
, DIB_RGB_COLORS
, &src_bits
, NULL
, 0 ))) goto done
;
1316 if (!(hdc
= CreateCompatibleDC( 0 ))) goto done
;
1318 SelectObject( hdc
, dib
);
1320 surface
->funcs
->lock( surface
);
1324 IntersectRect( &rect
, &rect
, info
->prcDirty
);
1325 memcpy( src_bits
, dst_bits
, bmi
->bmiHeader
.biSizeImage
);
1326 PatBlt( hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, BLACKNESS
);
1329 if (info
->pptSrc
) OffsetRect( &src_rect
, info
->pptSrc
->x
, info
->pptSrc
->y
);
1330 DPtoLP( info
->hdcSrc
, (POINT
*)&src_rect
, 2 );
1332 ret
= GdiAlphaBlend( hdc
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
1333 info
->hdcSrc
, src_rect
.left
, src_rect
.top
,
1334 src_rect
.right
- src_rect
.left
, src_rect
.bottom
- src_rect
.top
,
1335 (info
->dwFlags
& ULW_ALPHA
) ? *info
->pblend
: blend
);
1338 memcpy( dst_bits
, src_bits
, bmi
->bmiHeader
.biSizeImage
);
1339 add_bounds_rect( surface
->funcs
->get_bounds( surface
), &rect
);
1342 surface
->funcs
->unlock( surface
);
1343 surface
->funcs
->flush( surface
);
1346 window_surface_release( surface
);
1347 if (hdc
) DeleteDC( hdc
);
1348 if (dib
) DeleteObject( dib
);
1353 /**********************************************************************
1354 * ANDROID_WindowMessage
1356 LRESULT CDECL
ANDROID_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
1358 struct android_win_data
*data
;
1362 case WM_ANDROID_REFRESH
:
1363 if (wp
) /* opengl client window */
1365 update_gl_drawable( hwnd
);
1367 else if ((data
= get_win_data( hwnd
)))
1369 struct window_surface
*surface
= data
->surface
;
1372 surface
->funcs
->lock( surface
);
1373 *surface
->funcs
->get_bounds( surface
) = surface
->rect
;
1374 surface
->funcs
->unlock( surface
);
1375 if (is_argb_surface( surface
)) surface
->funcs
->flush( surface
);
1377 release_win_data( data
);
1381 FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg
, hwnd
, wp
, lp
);
1387 /***********************************************************************
1388 * ANDROID_create_desktop
1390 BOOL CDECL
ANDROID_create_desktop( UINT width
, UINT height
)
1392 desktop_orig_wndproc
= (WNDPROC
)SetWindowLongPtrW( GetDesktopWindow(), GWLP_WNDPROC
,
1393 (LONG_PTR
)desktop_wndproc_wrapper
);
1395 /* wait until we receive the surface changed event */
1396 while (!screen_width
)
1398 if (wait_events( 2000 ) != 1)
1400 ERR( "wait timed out\n" );
1403 process_events( QS_ALLINPUT
);