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 /***********************************************************************
109 static struct android_win_data
*alloc_win_data( HWND hwnd
)
111 struct android_win_data
*data
;
113 if ((data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
))))
116 data
->window
= create_ioctl_window( hwnd
);
117 EnterCriticalSection( &win_data_section
);
118 win_data_context
[context_idx(hwnd
)] = data
;
124 /***********************************************************************
127 static void free_win_data( struct android_win_data
*data
)
129 win_data_context
[context_idx( data
->hwnd
)] = NULL
;
130 LeaveCriticalSection( &win_data_section
);
131 if (data
->window
) release_ioctl_window( data
->window
);
132 HeapFree( GetProcessHeap(), 0, data
);
136 /***********************************************************************
139 * Lock and return the data structure associated with a window.
141 static struct android_win_data
*get_win_data( HWND hwnd
)
143 struct android_win_data
*data
;
145 if (!hwnd
) return NULL
;
146 EnterCriticalSection( &win_data_section
);
147 if ((data
= win_data_context
[context_idx(hwnd
)]) && data
->hwnd
== hwnd
) return data
;
148 LeaveCriticalSection( &win_data_section
);
153 /***********************************************************************
156 * Release the data returned by get_win_data.
158 static void release_win_data( struct android_win_data
*data
)
160 if (data
) LeaveCriticalSection( &win_data_section
);
164 /***********************************************************************
167 static struct ANativeWindow
*get_ioctl_window( HWND hwnd
)
169 struct ANativeWindow
*ret
;
170 struct android_win_data
*data
= get_win_data( hwnd
);
172 if (!data
|| !data
->window
) return NULL
;
173 ret
= grab_ioctl_window( data
->window
);
174 release_win_data( data
);
179 /* Handling of events coming from the Java side */
184 union event_data data
;
187 static struct list event_queue
= LIST_INIT( event_queue
);
188 static struct java_event
*current_event
;
189 static int event_pipe
[2];
190 static DWORD desktop_tid
;
192 /***********************************************************************
195 int send_event( const union event_data
*data
)
199 if ((res
= write( event_pipe
[1], data
, sizeof(*data
) )) != sizeof(*data
))
201 p__android_log_print( ANDROID_LOG_ERROR
, "wine", "failed to send event" );
208 /***********************************************************************
211 * JNI callback, runs in the context of the Java thread.
213 void desktop_changed( JNIEnv
*env
, jobject obj
, jint width
, jint height
)
215 union event_data data
;
217 memset( &data
, 0, sizeof(data
) );
218 data
.type
= DESKTOP_CHANGED
;
219 data
.desktop
.width
= width
;
220 data
.desktop
.height
= height
;
221 p__android_log_print( ANDROID_LOG_INFO
, "wine", "desktop_changed: %ux%u", width
, height
);
226 /***********************************************************************
229 * JNI callback, runs in the context of the Java thread.
231 void surface_changed( JNIEnv
*env
, jobject obj
, jint win
, jobject surface
)
233 union event_data data
;
235 memset( &data
, 0, sizeof(data
) );
236 data
.surface
.hwnd
= LongToHandle( win
);
240 ANativeWindow
*win
= pANativeWindow_fromSurface( env
, surface
);
242 if (win
->query( win
, NATIVE_WINDOW_WIDTH
, &width
) < 0) width
= 0;
243 if (win
->query( win
, NATIVE_WINDOW_HEIGHT
, &height
) < 0) height
= 0;
244 data
.surface
.window
= win
;
245 data
.surface
.width
= width
;
246 data
.surface
.height
= height
;
247 p__android_log_print( ANDROID_LOG_INFO
, "wine", "surface_changed: %p %ux%u",
248 data
.surface
.hwnd
, width
, height
);
250 data
.type
= SURFACE_CHANGED
;
255 /***********************************************************************
258 static void init_event_queue(void)
263 if (pipe2( event_pipe
, O_CLOEXEC
| O_NONBLOCK
) == -1)
265 ERR( "could not create data\n" );
268 if (wine_server_fd_to_handle( event_pipe
[0], GENERIC_READ
| SYNCHRONIZE
, 0, &handle
))
270 ERR( "Can't allocate handle for event fd\n" );
273 SERVER_START_REQ( set_queue_fd
)
275 req
->handle
= wine_server_obj_handle( handle
);
276 ret
= wine_server_call( req
);
281 ERR( "Can't store handle for event fd %x\n", ret
);
284 CloseHandle( handle
);
285 desktop_tid
= GetCurrentThreadId();
289 /***********************************************************************
292 * Pull events from the event pipe and add them to the queue
294 static void pull_events(void)
296 struct java_event
*event
;
301 if (!(event
= HeapAlloc( GetProcessHeap(), 0, sizeof(*event
) ))) break;
303 res
= read( event_pipe
[0], &event
->data
, sizeof(event
->data
) );
304 if (res
!= sizeof(event
->data
)) break;
305 list_add_tail( &event_queue
, &event
->entry
);
307 HeapFree( GetProcessHeap(), 0, event
);
311 /***********************************************************************
314 static int process_events( DWORD mask
)
316 struct java_event
*event
, *next
, *previous
;
317 unsigned int count
= 0;
319 assert( GetCurrentThreadId() == desktop_tid
);
323 previous
= current_event
;
325 LIST_FOR_EACH_ENTRY_SAFE( event
, next
, &event_queue
, struct java_event
, entry
)
327 switch (event
->data
.type
)
329 case SURFACE_CHANGED
:
330 break; /* always process it to unblock other threads */
332 if (mask
& QS_SENDMESSAGE
) break;
333 continue; /* skip it */
336 /* remove it first, in case we process events recursively */
337 list_remove( &event
->entry
);
338 current_event
= event
;
340 switch (event
->data
.type
)
342 case DESKTOP_CHANGED
:
343 TRACE( "DESKTOP_CHANGED %ux%u\n", event
->data
.desktop
.width
, event
->data
.desktop
.height
);
344 screen_width
= event
->data
.desktop
.width
;
345 screen_height
= event
->data
.desktop
.height
;
346 init_monitors( screen_width
, screen_height
);
347 SetWindowPos( GetDesktopWindow(), 0, 0, 0, screen_width
, screen_height
,
348 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
351 case SURFACE_CHANGED
:
352 TRACE("SURFACE_CHANGED %p %p size %ux%u\n", event
->data
.surface
.hwnd
,
353 event
->data
.surface
.window
, event
->data
.surface
.width
, event
->data
.surface
.height
);
355 register_native_window( event
->data
.surface
.hwnd
, event
->data
.surface
.window
);
359 FIXME( "got event %u\n", event
->data
.type
);
361 HeapFree( GetProcessHeap(), 0, event
);
364 current_event
= previous
;
369 /***********************************************************************
372 static int wait_events( int timeout
)
374 assert( GetCurrentThreadId() == desktop_tid
);
378 struct pollfd pollfd
;
381 pollfd
.fd
= event_pipe
[0];
382 pollfd
.events
= POLLIN
| POLLHUP
;
383 ret
= poll( &pollfd
, 1, timeout
);
384 if (ret
== -1 && errno
== EINTR
) continue;
385 if (ret
&& (pollfd
.revents
& (POLLHUP
| POLLERR
))) ret
= -1;
391 /* Window surface support */
393 struct android_window_surface
395 struct window_surface header
;
397 ANativeWindow
*window
;
400 RGNDATA
*region_data
;
405 CRITICAL_SECTION crit
;
406 BITMAPINFO info
; /* variable size, must be last */
409 static struct android_window_surface
*get_android_surface( struct window_surface
*surface
)
411 return (struct android_window_surface
*)surface
;
414 static inline void reset_bounds( RECT
*bounds
)
416 bounds
->left
= bounds
->top
= INT_MAX
;
417 bounds
->right
= bounds
->bottom
= INT_MIN
;
420 static inline void add_bounds_rect( RECT
*bounds
, const RECT
*rect
)
422 if (rect
->left
>= rect
->right
|| rect
->top
>= rect
->bottom
) return;
423 bounds
->left
= min( bounds
->left
, rect
->left
);
424 bounds
->top
= min( bounds
->top
, rect
->top
);
425 bounds
->right
= max( bounds
->right
, rect
->right
);
426 bounds
->bottom
= max( bounds
->bottom
, rect
->bottom
);
429 /* store the palette or color mask data in the bitmap info structure */
430 static void set_color_info( BITMAPINFO
*info
, BOOL has_alpha
)
432 DWORD
*colors
= (DWORD
*)info
->bmiColors
;
434 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
435 info
->bmiHeader
.biClrUsed
= 0;
436 info
->bmiHeader
.biBitCount
= 32;
439 info
->bmiHeader
.biCompression
= BI_RGB
;
442 info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
443 colors
[0] = 0xff0000;
444 colors
[1] = 0x00ff00;
445 colors
[2] = 0x0000ff;
448 /* apply the window region to a single line of the destination image. */
449 static void apply_line_region( DWORD
*dst
, int width
, int x
, int y
, const RECT
*rect
, const RECT
*end
)
451 while (rect
< end
&& rect
->top
<= y
&& width
> 0)
455 memset( dst
, 0, min( rect
->left
- x
, width
) * sizeof(*dst
) );
456 dst
+= rect
->left
- x
;
457 width
-= rect
->left
- x
;
462 dst
+= rect
->right
- x
;
463 width
-= rect
->right
- x
;
468 if (width
> 0) memset( dst
, 0, width
* sizeof(*dst
) );
471 /***********************************************************************
472 * android_surface_lock
474 static void android_surface_lock( struct window_surface
*window_surface
)
476 struct android_window_surface
*surface
= get_android_surface( window_surface
);
478 EnterCriticalSection( &surface
->crit
);
481 /***********************************************************************
482 * android_surface_unlock
484 static void android_surface_unlock( struct window_surface
*window_surface
)
486 struct android_window_surface
*surface
= get_android_surface( window_surface
);
488 LeaveCriticalSection( &surface
->crit
);
491 /***********************************************************************
492 * android_surface_get_bitmap_info
494 static void *android_surface_get_bitmap_info( struct window_surface
*window_surface
, BITMAPINFO
*info
)
496 struct android_window_surface
*surface
= get_android_surface( window_surface
);
498 memcpy( info
, &surface
->info
, get_dib_info_size( &surface
->info
, DIB_RGB_COLORS
));
499 return surface
->bits
;
502 /***********************************************************************
503 * android_surface_get_bounds
505 static RECT
*android_surface_get_bounds( struct window_surface
*window_surface
)
507 struct android_window_surface
*surface
= get_android_surface( window_surface
);
509 return &surface
->bounds
;
512 /***********************************************************************
513 * android_surface_set_region
515 static void android_surface_set_region( struct window_surface
*window_surface
, HRGN region
)
517 struct android_window_surface
*surface
= get_android_surface( window_surface
);
519 TRACE( "updating surface %p hwnd %p with %p\n", surface
, surface
->hwnd
, region
);
521 window_surface
->funcs
->lock( window_surface
);
524 if (surface
->region
) DeleteObject( surface
->region
);
529 if (!surface
->region
) surface
->region
= CreateRectRgn( 0, 0, 0, 0 );
530 CombineRgn( surface
->region
, region
, 0, RGN_COPY
);
532 window_surface
->funcs
->unlock( window_surface
);
533 set_surface_region( &surface
->header
, (HRGN
)1 );
536 /***********************************************************************
537 * android_surface_flush
539 static void android_surface_flush( struct window_surface
*window_surface
)
541 struct android_window_surface
*surface
= get_android_surface( window_surface
);
542 ANativeWindow_Buffer buffer
;
547 window_surface
->funcs
->lock( window_surface
);
548 SetRect( &rect
, 0, 0, surface
->header
.rect
.right
- surface
->header
.rect
.left
,
549 surface
->header
.rect
.bottom
- surface
->header
.rect
.top
);
550 needs_flush
= IntersectRect( &rect
, &rect
, &surface
->bounds
);
551 reset_bounds( &surface
->bounds
);
552 window_surface
->funcs
->unlock( window_surface
);
553 if (!needs_flush
) return;
555 TRACE( "flushing %p hwnd %p surface %s rect %s bits %p alpha %02x key %08x region %u rects\n",
556 surface
, surface
->hwnd
, wine_dbgstr_rect( &surface
->header
.rect
),
557 wine_dbgstr_rect( &rect
), surface
->bits
, surface
->alpha
, surface
->color_key
,
558 surface
->region_data
? surface
->region_data
->rdh
.nCount
: 0 );
562 rc
.right
= rect
.right
;
563 rc
.bottom
= rect
.bottom
;
565 if (!surface
->window
->perform( surface
->window
, NATIVE_WINDOW_LOCK
, &buffer
, &rc
))
567 const RECT
*rgn_rect
= NULL
, *end
= NULL
;
568 unsigned int *src
, *dst
;
573 rect
.right
= rc
.right
;
574 rect
.bottom
= rc
.bottom
;
575 IntersectRect( &rect
, &rect
, &surface
->header
.rect
);
577 if (surface
->region_data
)
579 rgn_rect
= (RECT
*)surface
->region_data
->Buffer
;
580 end
= rgn_rect
+ surface
->region_data
->rdh
.nCount
;
582 src
= (unsigned int *)surface
->bits
583 + (rect
.top
- surface
->header
.rect
.top
) * surface
->info
.bmiHeader
.biWidth
584 + (rect
.left
- surface
->header
.rect
.left
);
585 dst
= (unsigned int *)buffer
.bits
+ rect
.top
* buffer
.stride
+ rect
.left
;
586 width
= min( rect
.right
- rect
.left
, buffer
.stride
);
588 for (y
= rect
.top
; y
< min( buffer
.height
, rect
.bottom
); y
++)
590 if (surface
->info
.bmiHeader
.biCompression
== BI_RGB
)
591 memcpy( dst
, src
, width
* sizeof(*dst
) );
592 else if (surface
->alpha
== 255)
593 for (x
= 0; x
< width
; x
++) dst
[x
] = src
[x
] | 0xff000000;
595 for (x
= 0; x
< width
; x
++)
596 dst
[x
] = ((surface
->alpha
<< 24) |
597 (((BYTE
)(src
[x
] >> 16) * surface
->alpha
/ 255) << 16) |
598 (((BYTE
)(src
[x
] >> 8) * surface
->alpha
/ 255) << 8) |
599 (((BYTE
)src
[x
] * surface
->alpha
/ 255)));
601 if (surface
->color_key
!= CLR_INVALID
)
602 for (x
= 0; x
< width
; x
++) if ((src
[x
] & 0xffffff) == surface
->color_key
) dst
[x
] = 0;
606 while (rgn_rect
< end
&& rgn_rect
->bottom
<= y
) rgn_rect
++;
607 apply_line_region( dst
, width
, rect
.left
, y
, rgn_rect
, end
);
610 src
+= surface
->info
.bmiHeader
.biWidth
;
611 dst
+= buffer
.stride
;
613 surface
->window
->perform( surface
->window
, NATIVE_WINDOW_UNLOCK_AND_POST
);
615 else TRACE( "Unable to lock surface %p window %p buffer %p\n",
616 surface
, surface
->hwnd
, surface
->window
);
619 /***********************************************************************
620 * android_surface_destroy
622 static void android_surface_destroy( struct window_surface
*window_surface
)
624 struct android_window_surface
*surface
= get_android_surface( window_surface
);
626 TRACE( "freeing %p bits %p\n", surface
, surface
->bits
);
628 surface
->crit
.DebugInfo
->Spare
[0] = 0;
629 DeleteCriticalSection( &surface
->crit
);
630 HeapFree( GetProcessHeap(), 0, surface
->region_data
);
631 if (surface
->region
) DeleteObject( surface
->region
);
632 release_ioctl_window( surface
->window
);
633 HeapFree( GetProcessHeap(), 0, surface
->bits
);
634 HeapFree( GetProcessHeap(), 0, surface
);
637 static const struct window_surface_funcs android_surface_funcs
=
639 android_surface_lock
,
640 android_surface_unlock
,
641 android_surface_get_bitmap_info
,
642 android_surface_get_bounds
,
643 android_surface_set_region
,
644 android_surface_flush
,
645 android_surface_destroy
648 static BOOL
is_argb_surface( struct window_surface
*surface
)
650 return surface
&& surface
->funcs
== &android_surface_funcs
&&
651 get_android_surface( surface
)->info
.bmiHeader
.biCompression
== BI_RGB
;
654 /***********************************************************************
657 static void set_color_key( struct android_window_surface
*surface
, COLORREF key
)
659 if (key
== CLR_INVALID
)
660 surface
->color_key
= CLR_INVALID
;
661 else if (surface
->info
.bmiHeader
.biBitCount
<= 8)
662 surface
->color_key
= CLR_INVALID
;
663 else if (key
& (1 << 24)) /* PALETTEINDEX */
664 surface
->color_key
= 0;
665 else if (key
>> 16 == 0x10ff) /* DIBINDEX */
666 surface
->color_key
= 0;
667 else if (surface
->info
.bmiHeader
.biBitCount
== 24)
668 surface
->color_key
= key
;
670 surface
->color_key
= (GetRValue(key
) << 16) | (GetGValue(key
) << 8) | GetBValue(key
);
673 /***********************************************************************
676 static void set_surface_region( struct window_surface
*window_surface
, HRGN win_region
)
678 struct android_window_surface
*surface
= get_android_surface( window_surface
);
679 struct android_win_data
*win_data
;
680 HRGN region
= win_region
;
681 RGNDATA
*data
= NULL
;
683 int offset_x
, offset_y
;
685 if (window_surface
->funcs
!= &android_surface_funcs
) return; /* we may get the null surface */
687 if (!(win_data
= get_win_data( surface
->hwnd
))) return;
688 offset_x
= win_data
->window_rect
.left
- win_data
->whole_rect
.left
;
689 offset_y
= win_data
->window_rect
.top
- win_data
->whole_rect
.top
;
690 release_win_data( win_data
);
692 if (win_region
== (HRGN
)1) /* hack: win_region == 1 means retrieve region from server */
694 region
= CreateRectRgn( 0, 0, win_data
->window_rect
.right
- win_data
->window_rect
.left
,
695 win_data
->window_rect
.bottom
- win_data
->window_rect
.top
);
696 if (GetWindowRgn( surface
->hwnd
, region
) == ERROR
&& !surface
->region
) goto done
;
699 OffsetRgn( region
, offset_x
, offset_y
);
700 if (surface
->region
) CombineRgn( region
, region
, surface
->region
, RGN_AND
);
702 if (!(size
= GetRegionData( region
, 0, NULL
))) goto done
;
703 if (!(data
= HeapAlloc( GetProcessHeap(), 0, size
))) goto done
;
705 if (!GetRegionData( region
, size
, data
))
707 HeapFree( GetProcessHeap(), 0, data
);
712 window_surface
->funcs
->lock( window_surface
);
713 HeapFree( GetProcessHeap(), 0, surface
->region_data
);
714 surface
->region_data
= data
;
715 *window_surface
->funcs
->get_bounds( window_surface
) = surface
->header
.rect
;
716 window_surface
->funcs
->unlock( window_surface
);
717 if (region
!= win_region
) DeleteObject( region
);
720 /***********************************************************************
723 static struct window_surface
*create_surface( HWND hwnd
, const RECT
*rect
,
724 BYTE alpha
, COLORREF color_key
, BOOL src_alpha
)
726 struct android_window_surface
*surface
;
727 int width
= rect
->right
- rect
->left
, height
= rect
->bottom
- rect
->top
;
729 surface
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
730 FIELD_OFFSET( struct android_window_surface
, info
.bmiColors
[3] ));
731 if (!surface
) return NULL
;
732 set_color_info( &surface
->info
, src_alpha
);
733 surface
->info
.bmiHeader
.biWidth
= width
;
734 surface
->info
.bmiHeader
.biHeight
= -height
; /* top-down */
735 surface
->info
.bmiHeader
.biPlanes
= 1;
736 surface
->info
.bmiHeader
.biSizeImage
= get_dib_image_size( &surface
->info
);
738 InitializeCriticalSection( &surface
->crit
);
739 surface
->crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": surface");
741 surface
->header
.funcs
= &android_surface_funcs
;
742 surface
->header
.rect
= *rect
;
743 surface
->header
.ref
= 1;
744 surface
->hwnd
= hwnd
;
745 surface
->window
= get_ioctl_window( hwnd
);
746 surface
->alpha
= alpha
;
747 set_color_key( surface
, color_key
);
748 set_surface_region( &surface
->header
, (HRGN
)1 );
749 reset_bounds( &surface
->bounds
);
751 if (!(surface
->bits
= HeapAlloc( GetProcessHeap(), 0, surface
->info
.bmiHeader
.biSizeImage
)))
754 TRACE( "created %p hwnd %p %s bits %p-%p\n", surface
, hwnd
, wine_dbgstr_rect(rect
),
755 surface
->bits
, (char *)surface
->bits
+ surface
->info
.bmiHeader
.biSizeImage
);
757 return &surface
->header
;
760 android_surface_destroy( &surface
->header
);
765 static WNDPROC desktop_orig_wndproc
;
767 static LRESULT CALLBACK
desktop_wndproc_wrapper( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
771 case WM_PARENTNOTIFY
:
772 if (LOWORD(wp
) == WM_DESTROY
) destroy_ioctl_window( (HWND
)lp
);
775 return desktop_orig_wndproc( hwnd
, msg
, wp
, lp
);
779 /***********************************************************************
780 * ANDROID_MsgWaitForMultipleObjectsEx
782 DWORD CDECL
ANDROID_MsgWaitForMultipleObjectsEx( DWORD count
, const HANDLE
*handles
,
783 DWORD timeout
, DWORD mask
, DWORD flags
)
785 if (GetCurrentThreadId() == desktop_tid
)
787 /* don't process nested events */
788 if (current_event
) mask
= 0;
789 if (process_events( mask
)) return count
- 1;
791 return WaitForMultipleObjectsEx( count
, handles
, flags
& MWMO_WAITALL
,
792 timeout
, flags
& MWMO_ALERTABLE
);
795 /**********************************************************************
796 * ANDROID_CreateWindow
798 BOOL CDECL
ANDROID_CreateWindow( HWND hwnd
)
800 TRACE( "%p\n", hwnd
);
802 if (hwnd
== GetDesktopWindow())
804 struct android_win_data
*data
;
807 start_android_device();
808 desktop_orig_wndproc
= (WNDPROC
)SetWindowLongPtrW( hwnd
, GWLP_WNDPROC
,
809 (LONG_PTR
)desktop_wndproc_wrapper
);
810 if (!(data
= alloc_win_data( hwnd
))) return FALSE
;
811 release_win_data( data
);
817 /***********************************************************************
818 * ANDROID_DestroyWindow
820 void CDECL
ANDROID_DestroyWindow( HWND hwnd
)
822 struct android_win_data
*data
;
824 if (!(data
= get_win_data( hwnd
))) return;
826 if (data
->surface
) window_surface_release( data
->surface
);
827 data
->surface
= NULL
;
828 free_win_data( data
);
832 /***********************************************************************
835 * Create a data window structure for an existing window.
837 static struct android_win_data
*create_win_data( HWND hwnd
, const RECT
*window_rect
,
838 const RECT
*client_rect
)
840 struct android_win_data
*data
;
843 if (!(parent
= GetAncestor( hwnd
, GA_PARENT
))) return NULL
; /* desktop or HWND_MESSAGE */
845 if (parent
!= GetDesktopWindow())
847 if (!(data
= get_win_data( parent
)) &&
848 !(data
= create_win_data( parent
, NULL
, NULL
)))
850 release_win_data( data
);
853 if (!(data
= alloc_win_data( hwnd
))) return NULL
;
855 data
->parent
= (parent
== GetDesktopWindow()) ? 0 : parent
;
859 data
->whole_rect
= data
->window_rect
= *window_rect
;
860 data
->client_rect
= *client_rect
;
864 GetWindowRect( hwnd
, &data
->window_rect
);
865 MapWindowPoints( 0, parent
, (POINT
*)&data
->window_rect
, 2 );
866 data
->whole_rect
= data
->window_rect
;
867 GetClientRect( hwnd
, &data
->client_rect
);
868 MapWindowPoints( hwnd
, parent
, (POINT
*)&data
->client_rect
, 2 );
869 ioctl_window_pos_changed( hwnd
, &data
->window_rect
, &data
->client_rect
, &data
->whole_rect
,
870 GetWindowLongW( hwnd
, GWL_STYLE
), SWP_NOACTIVATE
,
871 GetWindow( hwnd
, GW_HWNDPREV
), GetWindow( hwnd
, GW_OWNER
));
877 static inline RECT
get_surface_rect( const RECT
*visible_rect
)
881 IntersectRect( &rect
, visible_rect
, &virtual_screen_rect
);
882 OffsetRect( &rect
, -visible_rect
->left
, -visible_rect
->top
);
885 rect
.right
= max( rect
.left
+ 32, (rect
.right
+ 31) & ~31 );
886 rect
.bottom
= max( rect
.top
+ 32, (rect
.bottom
+ 31) & ~31 );
891 /***********************************************************************
892 * ANDROID_WindowPosChanging
894 void CDECL
ANDROID_WindowPosChanging( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
895 const RECT
*window_rect
, const RECT
*client_rect
, RECT
*visible_rect
,
896 struct window_surface
**surface
)
898 struct android_win_data
*data
= get_win_data( hwnd
);
903 BOOL layered
= GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_LAYERED
;
905 TRACE( "win %p window %s client %s style %08x flags %08x\n",
906 hwnd
, wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
),
907 GetWindowLongW( hwnd
, GWL_STYLE
), swp_flags
);
909 if (!data
&& !(data
= create_win_data( hwnd
, window_rect
, client_rect
))) return;
911 *visible_rect
= *window_rect
;
913 /* create the window surface if necessary */
915 if (data
->parent
) goto done
;
916 if (swp_flags
& SWP_HIDEWINDOW
) goto done
;
917 if (is_argb_surface( data
->surface
)) goto done
;
919 surface_rect
= get_surface_rect( visible_rect
);
922 if (!memcmp( &data
->surface
->rect
, &surface_rect
, sizeof(surface_rect
) ))
924 /* existing surface is good enough */
925 window_surface_add_ref( data
->surface
);
926 if (*surface
) window_surface_release( *surface
);
927 *surface
= data
->surface
;
931 if (!(swp_flags
& SWP_SHOWWINDOW
) && !(GetWindowLongW( hwnd
, GWL_STYLE
) & WS_VISIBLE
)) goto done
;
933 if (!layered
|| !GetLayeredWindowAttributes( hwnd
, &key
, &alpha
, &flags
)) flags
= 0;
934 if (!(flags
& LWA_ALPHA
)) alpha
= 255;
935 if (!(flags
& LWA_COLORKEY
)) key
= CLR_INVALID
;
937 if (*surface
) window_surface_release( *surface
);
938 *surface
= create_surface( data
->hwnd
, &surface_rect
, alpha
, key
, FALSE
);
941 release_win_data( data
);
945 /***********************************************************************
946 * ANDROID_WindowPosChanged
948 void CDECL
ANDROID_WindowPosChanged( HWND hwnd
, HWND insert_after
, UINT swp_flags
,
949 const RECT
*window_rect
, const RECT
*client_rect
,
950 const RECT
*visible_rect
, const RECT
*valid_rects
,
951 struct window_surface
*surface
)
953 struct android_win_data
*data
;
954 DWORD new_style
= GetWindowLongW( hwnd
, GWL_STYLE
);
957 if (!(data
= get_win_data( hwnd
))) return;
959 data
->window_rect
= *window_rect
;
960 data
->whole_rect
= *visible_rect
;
961 data
->client_rect
= *client_rect
;
963 if (!is_argb_surface( data
->surface
))
965 if (surface
) window_surface_add_ref( surface
);
966 if (data
->surface
) window_surface_release( data
->surface
);
967 data
->surface
= surface
;
969 if (!data
->parent
) owner
= GetWindow( hwnd
, GW_OWNER
);
970 release_win_data( data
);
972 TRACE( "win %p window %s client %s style %08x owner %p flags %08x\n", hwnd
,
973 wine_dbgstr_rect(window_rect
), wine_dbgstr_rect(client_rect
), new_style
, owner
, swp_flags
);
975 ioctl_window_pos_changed( hwnd
, window_rect
, client_rect
, visible_rect
,
976 new_style
, swp_flags
, insert_after
, owner
);
980 /**********************************************************************
981 * ANDROID_WindowMessage
983 LRESULT CDECL
ANDROID_WindowMessage( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
985 struct android_win_data
*data
;
989 case WM_ANDROID_REFRESH
:
990 if ((data
= get_win_data( hwnd
)))
992 struct window_surface
*surface
= data
->surface
;
995 surface
->funcs
->lock( surface
);
996 *surface
->funcs
->get_bounds( surface
) = surface
->rect
;
997 surface
->funcs
->unlock( surface
);
998 if (is_argb_surface( surface
)) surface
->funcs
->flush( surface
);
1000 release_win_data( data
);
1004 FIXME( "got window msg %x hwnd %p wp %lx lp %lx\n", msg
, hwnd
, wp
, lp
);
1010 /***********************************************************************
1011 * ANDROID_create_desktop
1013 BOOL CDECL
ANDROID_create_desktop( UINT width
, UINT height
)
1015 /* wait until we receive the surface changed event */
1016 while (!screen_width
)
1018 if (wait_events( 2000 ) != 1)
1020 ERR( "wait timed out\n" );
1023 process_events( QS_ALLINPUT
);