1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <unistd.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <limits.h>
36
37 #include <directfb.h>
38
39 #include <direct/debug.h>
40 #include <direct/mem.h>
41 #include <direct/memcpy.h>
42 #include <direct/messages.h>
43 #include <direct/trace.h>
44 #include <direct/util.h>
45
46 #include <fusion/reactor.h>
47 #include <fusion/shmalloc.h>
48 #include <fusion/vector.h>
49
50 #include <core/core.h>
51 #include <core/coredefs.h>
52 #include <core/coretypes.h>
53
54 #include <core/gfxcard.h>
55 #include <core/layer_context.h>
56 #include <core/layer_region.h>
57 #include <core/layers_internal.h>
58 #include <core/surface.h>
59 #include <core/palette.h>
60 #include <core/windows.h>
61 #include <core/windows_internal.h>
62 #include <core/windowstack.h>
63 #include <core/wm.h>
64
65 #include <gfx/util.h>
66
67 #include <misc/conf.h>
68 #include <misc/util.h>
69
70 #include <core/wm_module.h>
71
72 #include <unique/context.h>
73 #include <unique/stret.h>
74 #include <unique/internal.h>
75
76
77 D_DEBUG_DOMAIN( WM_Unique, "WM/UniQuE", "UniQuE - Universal Quark Emitter" );
78
79
80 DFB_WINDOW_MANAGER( unique );
81
82 /**************************************************************************************************/
83
84 typedef struct {
85 int magic;
86
87 CoreWindowStack *stack;
88
89 UniqueContext *context;
90
91 GlobalReaction context_reaction;
92 } StackData;
93
94 typedef struct {
95 int magic;
96
97 UniqueContext *context;
98
99 UniqueWindow *window;
100
101 GlobalReaction window_reaction;
102 } WindowData;
103
104 /**************************************************************************************************/
105
106 static ReactionResult
context_notify(WMData * data,const UniqueContextNotification * notification,void * ctx)107 context_notify( WMData *data,
108 const UniqueContextNotification *notification,
109 void *ctx )
110 {
111 StackData *stack_data = ctx;
112
113 D_ASSERT( data != NULL );
114
115 D_ASSERT( notification != NULL );
116 D_ASSERT( notification->context != NULL );
117
118 D_MAGIC_ASSERT( stack_data, StackData );
119
120 D_ASSERT( notification->context == stack_data->context );
121
122 D_MAGIC_ASSERT( stack_data->context, UniqueContext );
123
124 D_ASSERT( ! D_FLAGS_IS_SET( notification->flags, ~UCNF_ALL ) );
125
126 D_DEBUG_AT( WM_Unique, "context_notify( wm_data %p, stack_data %p )\n", data, stack_data );
127
128 if (notification->flags & UCNF_DESTROYED) {
129 D_DEBUG_AT( WM_Unique, " -> context destroyed.\n" );
130
131 if (notification->context == stack_data->context)
132 stack_data->context = NULL;
133
134 return RS_REMOVE;
135 }
136
137 return RS_OK;
138 }
139
140 static ReactionResult
window_notify(WMData * data,const UniqueWindowNotification * notification,void * ctx)141 window_notify( WMData *data,
142 const UniqueWindowNotification *notification,
143 void *ctx )
144 {
145 WindowData *window_data = ctx;
146
147 D_ASSERT( data != NULL );
148
149 D_ASSERT( notification != NULL );
150 D_ASSERT( notification->window != NULL );
151
152 D_MAGIC_ASSERT( window_data, WindowData );
153
154 D_ASSERT( notification->window == window_data->window );
155
156 D_MAGIC_ASSERT( window_data->window, UniqueWindow );
157
158 D_ASSERT( ! D_FLAGS_IS_SET( notification->flags, ~UWNF_ALL ) );
159
160 D_DEBUG_AT( WM_Unique, "window_notify( wm_data %p, window_data %p )\n", data, window_data );
161
162 if (notification->flags & UWNF_DESTROYED) {
163 D_DEBUG_AT( WM_Unique, " -> window destroyed.\n" );
164
165 window_data->window = NULL;
166
167 return RS_REMOVE;
168 }
169
170 return RS_OK;
171 }
172
173 /**************************************************************************************************/
174
175 static void
initialize_data(CoreDFB * core,WMData * data,WMShared * shared)176 initialize_data( CoreDFB *core, WMData *data, WMShared *shared )
177 {
178 D_ASSERT( data != NULL );
179
180 /* Initialize local data. */
181 data->core = core;
182 data->world = dfb_core_world( core );
183 data->shared = shared;
184 data->module_abi = UNIQUE_WM_ABI_VERSION;
185
186 /* Set module callbacks. */
187 data->context_notify = context_notify;
188 data->window_notify = window_notify;
189 }
190
191 /**************************************************************************************************/
192
193 static void
wm_get_info(CoreWMInfo * info)194 wm_get_info( CoreWMInfo *info )
195 {
196 info->version.major = 0;
197 info->version.minor = 4;
198 info->version.binary = UNIQUE_WM_ABI_VERSION;
199
200 snprintf( info->name, DFB_CORE_WM_INFO_NAME_LENGTH, "UniQuE" );
201 snprintf( info->vendor, DFB_CORE_WM_INFO_VENDOR_LENGTH, "Denis Oliver Kropp" );
202
203 info->wm_data_size = sizeof(WMData);
204 info->wm_shared_size = sizeof(WMShared);
205 info->stack_data_size = sizeof(StackData);
206 info->window_data_size = sizeof(WindowData);
207 }
208
209 static DFBResult
wm_initialize(CoreDFB * core,void * wm_data,void * shared_data)210 wm_initialize( CoreDFB *core, void *wm_data, void *shared_data )
211 {
212 WMData *data = wm_data;
213 WMShared *shared = shared_data;
214
215 D_DEBUG_AT( WM_Unique, "wm_initialize()\n" );
216
217 initialize_data( core, data, shared );
218
219 D_MAGIC_SET( shared, WMShared );
220
221 return unique_wm_module_init( core, data, shared, true );
222 }
223
224 static DFBResult
wm_join(CoreDFB * core,void * wm_data,void * shared_data)225 wm_join( CoreDFB *core, void *wm_data, void *shared_data )
226 {
227 WMData *data = wm_data;
228 WMShared *shared = shared_data;
229
230 D_DEBUG_AT( WM_Unique, "wm_join()\n" );
231
232 initialize_data( core, data, shared );
233
234 return unique_wm_module_init( core, data, shared, false );
235 }
236
237 static DFBResult
wm_shutdown(bool emergency,void * wm_data,void * shared_data)238 wm_shutdown( bool emergency, void *wm_data, void *shared_data )
239 {
240 WMShared *shared = shared_data;
241
242 (void) shared;
243
244 D_DEBUG_AT( WM_Unique, "wm_shutdown()\n" );
245
246 unique_wm_module_deinit( wm_data, shared_data, true, emergency );
247
248 D_MAGIC_CLEAR( shared );
249
250 return DFB_OK;
251 }
252
253 static DFBResult
wm_leave(bool emergency,void * wm_data,void * shared_data)254 wm_leave( bool emergency, void *wm_data, void *shared_data )
255 {
256 D_DEBUG_AT( WM_Unique, "wm_leave()\n" );
257
258 unique_wm_module_deinit( wm_data, shared_data, false, emergency );
259
260 return DFB_OK;
261 }
262
263 static DFBResult
wm_suspend(void * wm_data,void * shared_data)264 wm_suspend( void *wm_data, void *shared_data )
265 {
266 D_DEBUG_AT( WM_Unique, "wm_suspend()\n" );
267
268 return DFB_OK;
269 }
270
271 static DFBResult
wm_resume(void * wm_data,void * shared_data)272 wm_resume( void *wm_data, void *shared_data )
273 {
274 D_DEBUG_AT( WM_Unique, "wm_resume()\n" );
275
276 return DFB_OK;
277 }
278
279 static DFBResult
wm_post_init(void * wm_data,void * shared_data)280 wm_post_init( void *wm_data, void *shared_data )
281 {
282 D_DEBUG_AT( WM_Unique, "wm_post_init()\n" );
283
284 return DFB_OK;
285 }
286
287 /**************************************************************************************************/
288
289 static DFBResult
wm_init_stack(CoreWindowStack * stack,void * wm_data,void * stack_data)290 wm_init_stack( CoreWindowStack *stack,
291 void *wm_data,
292 void *stack_data )
293 {
294 DFBResult ret;
295 StackData *data = stack_data;
296 WMData *wmdata = wm_data;
297 CoreLayerContext *context;
298 CoreLayerRegion *region;
299
300 D_ASSERT( stack != NULL );
301 D_ASSERT( stack->context != NULL );
302 D_ASSERT( wm_data != NULL );
303 D_ASSERT( stack_data != NULL );
304
305 context = stack->context;
306
307 D_ASSERT( context != NULL );
308
309 ret = dfb_layer_context_get_primary_region( context, true, ®ion );
310 if (ret) {
311 D_DERROR( ret, "WM/UniQuE: Could not get the primary region!\n" );
312 return ret;
313 }
314
315 /* Create the unique context. */
316 ret = unique_context_create( wmdata->core, stack, region, context->layer_id,
317 wmdata->shared, &data->context );
318 dfb_layer_region_unref( region );
319 if (ret) {
320 D_DERROR( ret, "WM/UniQuE: Could not create the context!\n" );
321 return ret;
322 }
323
324 /* Attach the global context listener. */
325 ret = unique_context_attach_global( data->context,
326 UNIQUE_WM_MODULE_CONTEXT_LISTENER,
327 data, &data->context_reaction );
328 if (ret) {
329 unique_context_unref( data->context );
330 D_DERROR( ret, "WM/UniQuE: Could not attach global context listener!\n" );
331 return ret;
332 }
333
334 /* Inherit all local references from the layer context. */
335 ret = unique_context_inherit( data->context, context );
336 unique_context_unref( data->context );
337 if (ret) {
338 unique_context_detach_global( data->context, &data->context_reaction );
339 D_DERROR( ret, "WM/UniQuE: Could not inherit from layer context!\n" );
340 return ret;
341 }
342
343
344
345 data->stack = stack;
346
347 D_MAGIC_SET( data, StackData );
348
349 return DFB_OK;
350 }
351
352 static DFBResult
wm_close_stack(CoreWindowStack * stack,void * wm_data,void * stack_data)353 wm_close_stack( CoreWindowStack *stack,
354 void *wm_data,
355 void *stack_data )
356 {
357 StackData *data = stack_data;
358
359 D_ASSERT( stack != NULL );
360 D_ASSERT( wm_data != NULL );
361 D_ASSERT( stack_data != NULL );
362
363 D_MAGIC_ASSERT( data, StackData );
364
365 D_ASSUME( data->context == NULL );
366
367 if (data->context)
368 unique_context_detach_global( data->context, &data->context_reaction );
369
370 D_MAGIC_CLEAR( data );
371
372 return DFB_OK;
373 }
374
375 static DFBResult
wm_set_active(CoreWindowStack * stack,void * wm_data,void * stack_data,bool active)376 wm_set_active( CoreWindowStack *stack,
377 void *wm_data,
378 void *stack_data,
379 bool active )
380 {
381 StackData *data = stack_data;
382
383 D_ASSERT( stack != NULL );
384 D_ASSERT( wm_data != NULL );
385 D_ASSERT( stack_data != NULL );
386
387 D_MAGIC_ASSERT( data, StackData );
388
389 D_DEBUG_AT( WM_Unique, "%s( stack %p, wm_data %p, stack_data %p, %sactive )\n",
390 __FUNCTION__, stack, wm_data, stack_data, active ? "" : "in" );
391
392 if (!data->context) {
393 D_ASSERT( !active );
394 return DFB_OK;
395 }
396
397 return unique_context_set_active( data->context, active );
398 }
399
400 static DFBResult
wm_resize_stack(CoreWindowStack * stack,void * wm_data,void * stack_data,int width,int height)401 wm_resize_stack( CoreWindowStack *stack,
402 void *wm_data,
403 void *stack_data,
404 int width,
405 int height )
406 {
407 StackData *data = stack_data;
408
409 D_ASSERT( stack != NULL );
410 D_ASSERT( wm_data != NULL );
411 D_ASSERT( stack_data != NULL );
412
413 D_MAGIC_ASSERT( data, StackData );
414
415 if (!data->context)
416 return DFB_DESTROYED;
417
418 return unique_context_resize( data->context, width, height );
419 }
420
421 static DFBResult
wm_process_input(CoreWindowStack * stack,void * wm_data,void * stack_data,const DFBInputEvent * event)422 wm_process_input( CoreWindowStack *stack,
423 void *wm_data,
424 void *stack_data,
425 const DFBInputEvent *event )
426 {
427 StackData *data = stack_data;
428
429 (void) data;
430
431 D_ASSERT( stack != NULL );
432 D_ASSERT( wm_data != NULL );
433 D_ASSERT( stack_data != NULL );
434 D_ASSERT( event != NULL );
435
436 D_MAGIC_ASSERT( data, StackData );
437
438 return DFB_OK;
439 }
440
441 static DFBResult
wm_flush_keys(CoreWindowStack * stack,void * wm_data,void * stack_data)442 wm_flush_keys( CoreWindowStack *stack,
443 void *wm_data,
444 void *stack_data )
445 {
446 StackData *data = stack_data;
447
448 D_ASSERT( stack != NULL );
449 D_ASSERT( wm_data != NULL );
450 D_ASSERT( stack_data != NULL );
451
452 D_MAGIC_ASSERT( data, StackData );
453
454 if (!data->context)
455 return DFB_DESTROYED;
456
457 return unique_context_flush_keys( data->context );
458 }
459
460 static DFBResult
wm_window_at(CoreWindowStack * stack,void * wm_data,void * stack_data,int x,int y,CoreWindow ** ret_window)461 wm_window_at( CoreWindowStack *stack,
462 void *wm_data,
463 void *stack_data,
464 int x,
465 int y,
466 CoreWindow **ret_window )
467 {
468 DFBResult ret;
469 UniqueWindow *window;
470 StackData *data = stack_data;
471
472 D_ASSERT( stack != NULL );
473 D_ASSERT( wm_data != NULL );
474 D_ASSERT( stack_data != NULL );
475 D_ASSERT( ret_window != NULL );
476
477 D_MAGIC_ASSERT( data, StackData );
478
479 if (!data->context)
480 return DFB_DESTROYED;
481
482 ret = unique_context_window_at( data->context, x, y, &window );
483 if (ret)
484 return ret;
485
486 D_MAGIC_ASSERT( window, UniqueWindow );
487
488 *ret_window = window->window;
489
490 return DFB_OK;
491 }
492
493 static DFBResult
wm_window_lookup(CoreWindowStack * stack,void * wm_data,void * stack_data,DFBWindowID window_id,CoreWindow ** ret_window)494 wm_window_lookup( CoreWindowStack *stack,
495 void *wm_data,
496 void *stack_data,
497 DFBWindowID window_id,
498 CoreWindow **ret_window )
499 {
500 DFBResult ret;
501 UniqueWindow *window;
502 StackData *data = stack_data;
503
504 D_ASSERT( stack != NULL );
505 D_ASSERT( wm_data != NULL );
506 D_ASSERT( stack_data != NULL );
507 D_ASSERT( ret_window != NULL );
508
509 D_MAGIC_ASSERT( data, StackData );
510
511 if (!data->context)
512 return DFB_DESTROYED;
513
514 ret = unique_context_lookup_window( data->context, window_id, &window );
515 if (ret)
516 return ret;
517
518 D_MAGIC_ASSERT( window, UniqueWindow );
519
520 *ret_window = window->window;
521
522 return DFB_OK;
523 }
524
525 static DFBResult
wm_enum_windows(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWMWindowCallback callback,void * callback_ctx)526 wm_enum_windows( CoreWindowStack *stack,
527 void *wm_data,
528 void *stack_data,
529 CoreWMWindowCallback callback,
530 void *callback_ctx )
531 {
532 StackData *data = stack_data;
533
534 D_ASSERT( stack != NULL );
535 D_ASSERT( wm_data != NULL );
536 D_ASSERT( stack_data != NULL );
537 D_ASSERT( callback != NULL );
538
539 D_MAGIC_ASSERT( data, StackData );
540
541 if (!data->context)
542 return DFB_DESTROYED;
543
544 return unique_context_enum_windows( data->context, callback, callback_ctx );
545 }
546
547 /**************************************************************************************************/
548
549 static DFBResult
wm_get_insets(CoreWindowStack * stack,CoreWindow * window,DFBInsets * insets)550 wm_get_insets( CoreWindowStack *stack,
551 CoreWindow *window,
552 DFBInsets *insets )
553 {
554 if( insets ) {
555 insets->l=0;
556 insets->t=0;
557 insets->r=0;
558 insets->b=0;
559 }
560 return DFB_OK;
561 }
562
563 static DFBResult
wm_preconfigure_window(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWindow * window,void * window_data)564 wm_preconfigure_window( CoreWindowStack *stack,
565 void *wm_data,
566 void *stack_data,
567 CoreWindow *window,
568 void *window_data )
569 {
570 return DFB_OK;
571 }
572
573 static DFBResult
wm_set_window_property(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWindow * window,void * window_data,const char * key,void * value,void ** ret_old_value)574 wm_set_window_property( CoreWindowStack *stack,
575 void *wm_data,
576 void *stack_data,
577 CoreWindow *window,
578 void *window_data,
579 const char *key,
580 void *value,
581 void **ret_old_value )
582 {
583 D_ASSERT( stack != NULL );
584 D_ASSERT( wm_data != NULL );
585 D_ASSERT( stack_data != NULL );
586 D_ASSERT( window != NULL );
587 D_ASSERT( window_data != NULL );
588 D_ASSERT( key != NULL );
589
590 fusion_object_set_property((FusionObject*)window,
591 key,value,ret_old_value);
592 return DFB_OK;
593 }
594
595 static DFBResult
wm_get_window_property(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWindow * window,void * window_data,const char * key,void ** ret_value)596 wm_get_window_property( CoreWindowStack *stack,
597 void *wm_data,
598 void *stack_data,
599 CoreWindow *window,
600 void *window_data,
601 const char *key,
602 void **ret_value )
603 {
604 D_ASSERT( stack != NULL );
605 D_ASSERT( wm_data != NULL );
606 D_ASSERT( stack_data != NULL );
607 D_ASSERT( window != NULL );
608 D_ASSERT( window_data != NULL );
609 D_ASSERT( key != NULL );
610 D_ASSERT( ret_value != NULL );
611
612 *ret_value=fusion_object_get_property((FusionObject*)window,key);
613 return DFB_OK;
614 }
615
616
617 static DFBResult
wm_remove_window_property(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWindow * window,void * window_data,const char * key,void ** ret_value)618 wm_remove_window_property( CoreWindowStack *stack,
619 void *wm_data,
620 void *stack_data,
621 CoreWindow *window,
622 void *window_data,
623 const char *key,
624 void **ret_value )
625 {
626 D_ASSERT( stack != NULL );
627 D_ASSERT( wm_data != NULL );
628 D_ASSERT( stack_data != NULL );
629 D_ASSERT( window != NULL );
630 D_ASSERT( window_data != NULL );
631 D_ASSERT( key != NULL );
632
633 fusion_object_remove_property((FusionObject*)window,key,ret_value);
634 return DFB_OK;
635 }
636
637 static DFBResult
wm_add_window(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWindow * window,void * window_data)638 wm_add_window( CoreWindowStack *stack,
639 void *wm_data,
640 void *stack_data,
641 CoreWindow *window,
642 void *window_data )
643 {
644 DFBResult ret;
645 StackData *sdata = stack_data;
646 WindowData *data = window_data;
647 WMData *wmdata = wm_data;
648
649 D_ASSERT( stack != NULL );
650 D_ASSERT( wm_data != NULL );
651 D_ASSERT( stack_data != NULL );
652 D_ASSERT( window != NULL );
653 D_ASSERT( window_data != NULL );
654
655 D_MAGIC_ASSERT( sdata, StackData );
656 D_MAGIC_ASSERT( sdata->context, UniqueContext );
657
658 data->context = sdata->context;
659
660 /* Create the unique window. */
661 ret = unique_window_create( wmdata->core, window, data->context,
662 window->caps, &window->config, &data->window );
663 if (ret) {
664 D_DERROR( ret, "WM/UniQuE: Could not create window!\n" );
665 return ret;
666 }
667
668 /* Attach the global window listener. */
669 ret = unique_window_attach_global( data->window,
670 UNIQUE_WM_MODULE_WINDOW_LISTENER,
671 data, &data->window_reaction );
672 if (ret) {
673 unique_window_unref( data->window );
674 D_DERROR( ret, "WM/UniQuE: Could not attach global window listener!\n" );
675 return ret;
676 }
677
678 /* Inherit all local references from the layer window. */
679 ret = unique_window_inherit( data->window, window );
680 unique_window_unref( data->window );
681 if (ret) {
682 unique_window_detach_global( data->window, &data->window_reaction );
683 D_DERROR( ret, "WM/UniQuE: Could not inherit from core window!\n" );
684 return ret;
685 }
686
687 unique_window_get_config( data->window, &window->config );
688
689
690 D_MAGIC_SET( data, WindowData );
691
692 return DFB_OK;
693 }
694
695 static DFBResult
wm_remove_window(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreWindow * window,void * window_data)696 wm_remove_window( CoreWindowStack *stack,
697 void *wm_data,
698 void *stack_data,
699 CoreWindow *window,
700 void *window_data )
701 {
702 WindowData *data = window_data;
703
704 D_ASSERT( stack != NULL );
705 D_ASSERT( wm_data != NULL );
706 D_ASSERT( stack_data != NULL );
707 D_ASSERT( window != NULL );
708 D_ASSERT( window_data != NULL );
709
710 D_MAGIC_ASSERT( data, WindowData );
711
712 // D_ASSUME( data->window == NULL );
713
714 if (data->window)
715 unique_window_detach_global( data->window, &data->window_reaction );
716
717 D_MAGIC_CLEAR( data );
718
719 return DFB_OK;
720 }
721
722 static DFBResult
wm_set_window_config(CoreWindow * window,void * wm_data,void * window_data,const CoreWindowConfig * config,CoreWindowConfigFlags flags)723 wm_set_window_config( CoreWindow *window,
724 void *wm_data,
725 void *window_data,
726 const CoreWindowConfig *config,
727 CoreWindowConfigFlags flags )
728 {
729 DFBResult ret;
730 WindowData *data = window_data;
731
732 D_ASSERT( window != NULL );
733 D_ASSERT( wm_data != NULL );
734 D_ASSERT( window_data != NULL );
735 D_ASSERT( config != NULL );
736
737 D_MAGIC_ASSERT( data, WindowData );
738
739 if (!data->window)
740 return DFB_DESTROYED;
741
742 ret = unique_window_set_config( data->window, config, flags );
743
744 unique_window_get_config( data->window, &window->config );
745
746 return ret;
747 }
748
749 static DFBResult
wm_restack_window(CoreWindow * window,void * wm_data,void * window_data,CoreWindow * relative,void * relative_data,int relation)750 wm_restack_window( CoreWindow *window,
751 void *wm_data,
752 void *window_data,
753 CoreWindow *relative,
754 void *relative_data,
755 int relation )
756 {
757 WindowData *data = window_data;
758 WindowData *rel_data = relative_data;
759
760 D_ASSERT( window != NULL );
761 D_ASSERT( wm_data != NULL );
762 D_ASSERT( window_data != NULL );
763
764 D_MAGIC_ASSERT( data, WindowData );
765
766 D_ASSERT( relative == NULL || relative_data != NULL );
767
768 D_ASSERT( relative == NULL || relative == window || relation != 0);
769
770 if (!data->window)
771 return DFB_DESTROYED;
772
773 return unique_window_restack( data->window, rel_data ? rel_data->window : NULL, relation );
774 }
775
776 static DFBResult
wm_grab(CoreWindow * window,void * wm_data,void * window_data,CoreWMGrab * grab)777 wm_grab( CoreWindow *window,
778 void *wm_data,
779 void *window_data,
780 CoreWMGrab *grab )
781 {
782 WindowData *data = window_data;
783
784 D_ASSERT( window != NULL );
785 D_ASSERT( wm_data != NULL );
786 D_ASSERT( window_data != NULL );
787 D_ASSERT( grab != NULL );
788
789 D_MAGIC_ASSERT( data, WindowData );
790
791 if (!data->window)
792 return DFB_DESTROYED;
793
794 return unique_window_grab( data->window, grab );
795 }
796
797 static DFBResult
wm_ungrab(CoreWindow * window,void * wm_data,void * window_data,CoreWMGrab * grab)798 wm_ungrab( CoreWindow *window,
799 void *wm_data,
800 void *window_data,
801 CoreWMGrab *grab )
802 {
803 WindowData *data = window_data;
804
805 D_ASSERT( window != NULL );
806 D_ASSERT( wm_data != NULL );
807 D_ASSERT( window_data != NULL );
808 D_ASSERT( grab != NULL );
809
810 D_MAGIC_ASSERT( data, WindowData );
811
812 if (!data->window)
813 return DFB_DESTROYED;
814
815 return unique_window_ungrab( data->window, grab );
816 }
817
818 static DFBResult
wm_request_focus(CoreWindow * window,void * wm_data,void * window_data)819 wm_request_focus( CoreWindow *window,
820 void *wm_data,
821 void *window_data )
822 {
823 WindowData *data = window_data;
824
825 D_ASSERT( window != NULL );
826 D_ASSERT( wm_data != NULL );
827 D_ASSERT( window_data != NULL );
828
829 D_MAGIC_ASSERT( data, WindowData );
830
831 if (!data->window)
832 return DFB_DESTROYED;
833
834 return unique_window_request_focus( data->window );
835 }
836
837 static DFBResult
wm_begin_updates(CoreWindow * window,void * wm_data,void * window_data,const DFBRegion * update)838 wm_begin_updates( CoreWindow *window,
839 void *wm_data,
840 void *window_data,
841 const DFBRegion *update )
842 {
843 D_ASSERT( window != NULL );
844 D_ASSERT( wm_data != NULL );
845 D_ASSERT( window_data != NULL );
846
847 return DFB_OK;
848 }
849
850 static DFBResult
wm_set_cursor_position(CoreWindow * window,void * wm_data,void * window_data,int x,int y)851 wm_set_cursor_position( CoreWindow *window,
852 void *wm_data,
853 void *window_data,
854 int x,
855 int y )
856 {
857 D_ASSERT( window != NULL );
858 D_ASSERT( wm_data != NULL );
859 D_ASSERT( window_data != NULL );
860
861 D_UNIMPLEMENTED();
862
863 return DFB_UNIMPLEMENTED;
864 }
865
866 /**************************************************************************************************/
867
868 static DFBResult
wm_update_stack(CoreWindowStack * stack,void * wm_data,void * stack_data,const DFBRegion * region,DFBSurfaceFlipFlags flags)869 wm_update_stack( CoreWindowStack *stack,
870 void *wm_data,
871 void *stack_data,
872 const DFBRegion *region,
873 DFBSurfaceFlipFlags flags )
874 {
875 StackData *data = stack_data;
876
877 D_ASSERT( stack != NULL );
878 D_ASSERT( wm_data != NULL );
879 D_ASSERT( stack_data != NULL );
880
881 DFB_REGION_ASSERT( region );
882
883 D_MAGIC_ASSERT( data, StackData );
884
885 if (!data->context)
886 return DFB_DESTROYED;
887
888 return unique_context_update( data->context, region, 1, flags );
889 }
890
891 static DFBResult
wm_update_window(CoreWindow * window,void * wm_data,void * window_data,const DFBRegion * region,DFBSurfaceFlipFlags flags)892 wm_update_window( CoreWindow *window,
893 void *wm_data,
894 void *window_data,
895 const DFBRegion *region,
896 DFBSurfaceFlipFlags flags )
897 {
898 WindowData *data = window_data;
899
900 D_ASSERT( window != NULL );
901 D_ASSERT( wm_data != NULL );
902 D_ASSERT( window_data != NULL );
903
904 DFB_REGION_ASSERT_IF( region );
905
906 D_MAGIC_ASSERT( data, WindowData );
907
908 if (!data->window)
909 return DFB_DESTROYED;
910
911 return unique_window_update( data->window, region, flags );
912 }
913
914 /**************************************************************************************************/
915
916 /* HACK: implementation dumped in here for now, will move into context */
917 static DFBResult
wm_update_cursor(CoreWindowStack * stack,void * wm_data,void * stack_data,CoreCursorUpdateFlags flags)918 wm_update_cursor( CoreWindowStack *stack,
919 void *wm_data,
920 void *stack_data,
921 CoreCursorUpdateFlags flags )
922 {
923 DFBResult ret;
924 DFBRegion old_region;
925 WMData *wmdata = wm_data;
926 StackData *data = stack_data;
927 bool restored = false;
928 CoreLayer *layer;
929 CoreLayerRegion *region;
930 CardState *state;
931 CoreSurface *surface;
932 UniqueContext *context;
933
934 D_ASSERT( stack != NULL );
935 D_ASSERT( stack->context != NULL );
936 D_ASSERT( wm_data != NULL );
937 D_ASSERT( stack_data != NULL );
938
939 D_MAGIC_ASSERT( data, StackData );
940
941 context = data->context;
942
943 D_MAGIC_ASSERT( context, UniqueContext );
944
945 /* Optimize case of invisible cursor moving. */
946 if (!(flags & ~(CCUF_POSITION | CCUF_SHAPE)) && (!stack->cursor.opacity || !stack->cursor.enabled)) {
947 context->cursor_bs_valid = false;
948 return DFB_OK;
949 }
950
951 layer = dfb_layer_at( context->layer_id );
952 state = &layer->state;
953 region = context->region;
954 surface = context->surface;
955
956 D_ASSERT( region != NULL );
957 D_ASSERT( surface != NULL );
958
959 if (flags & CCUF_ENABLE) {
960 CoreSurface *cursor_bs;
961 DFBSurfaceCapabilities caps = DSCAPS_NONE;
962
963 dfb_surface_caps_apply_policy( stack->cursor.policy, &caps );
964
965 D_ASSERT( context->cursor_bs == NULL );
966
967 /* Create the cursor backing store surface. */
968 ret = dfb_surface_create_simple( wmdata->core, stack->cursor.size.w, stack->cursor.size.h,
969 region->config.format, caps, CSTF_SHARED | CSTF_CURSOR,
970 0, /* FIXME: no shared cursor objects, no cursor id */
971 NULL, &cursor_bs );
972 if (ret) {
973 D_ERROR( "WM/Default: Failed creating backing store for cursor!\n" );
974 return ret;
975 }
976
977 ret = dfb_surface_globalize( cursor_bs );
978 D_ASSERT( ret == DFB_OK );
979
980 /* Ensure valid back buffer for now.
981 * FIXME: Keep a flag to know when back/front have been swapped and need a sync.
982 */
983 switch (region->config.buffermode) {
984 case DLBM_BACKVIDEO:
985 case DLBM_TRIPLE:
986 dfb_gfx_copy( surface, surface, NULL );
987 break;
988
989 default:
990 break;
991 }
992
993 context->cursor_bs = cursor_bs;
994 }
995 else {
996 D_ASSERT( context->cursor_bs != NULL );
997
998 /* restore region under cursor */
999 if (context->cursor_drawn) {
1000 DFBRectangle rect = { 0, 0,
1001 context->cursor_region.x2 - context->cursor_region.x1 + 1,
1002 context->cursor_region.y2 - context->cursor_region.y1 + 1 };
1003
1004 D_ASSERT( stack->cursor.opacity || (flags & CCUF_OPACITY) );
1005 D_ASSERT( context->cursor_bs_valid );
1006
1007 dfb_gfx_copy_to( context->cursor_bs, surface, &rect,
1008 context->cursor_region.x1, context->cursor_region.y1, false );
1009
1010 context->cursor_drawn = false;
1011
1012 old_region = context->cursor_region;
1013 restored = true;
1014 }
1015
1016 if (flags & CCUF_SIZE) {
1017 ret = dfb_surface_reformat( context->cursor_bs,
1018 stack->cursor.size.w, stack->cursor.size.h,
1019 context->cursor_bs->config.format );
1020 if (ret) {
1021 D_ERROR( "WM/Default: Failed resizing backing store for cursor!\n" );
1022 return ret;
1023 }
1024 }
1025 }
1026
1027 if (flags & (CCUF_ENABLE | CCUF_POSITION | CCUF_SIZE | CCUF_OPACITY)) {
1028 context->cursor_bs_valid = false;
1029
1030 context->cursor_region.x1 = stack->cursor.x - stack->cursor.hot.x;
1031 context->cursor_region.y1 = stack->cursor.y - stack->cursor.hot.y;
1032 context->cursor_region.x2 = context->cursor_region.x1 + stack->cursor.size.w - 1;
1033 context->cursor_region.y2 = context->cursor_region.y1 + stack->cursor.size.h - 1;
1034
1035 if (!dfb_region_intersect( &context->cursor_region, 0, 0, stack->width - 1, stack->height - 1 )) {
1036 D_BUG( "invalid cursor region" );
1037 return DFB_BUG;
1038 }
1039 }
1040
1041 D_ASSERT( context->cursor_bs != NULL );
1042
1043 if (flags & CCUF_DISABLE) {
1044 dfb_surface_unlink( &context->cursor_bs );
1045 }
1046 else if (stack->cursor.opacity) {
1047 /* backup region under cursor */
1048 if (!context->cursor_bs_valid) {
1049 DFBRectangle rect = DFB_RECTANGLE_INIT_FROM_REGION( &context->cursor_region );
1050
1051 D_ASSERT( !context->cursor_drawn );
1052
1053 /* FIXME: this requires using blitted flipping all the time,
1054 but fixing it seems impossible, for now DSFLIP_BLIT is forced
1055 in repaint_stack() when the cursor is enabled. */
1056 dfb_gfx_copy_to( surface, context->cursor_bs, &rect, 0, 0, true );
1057
1058 context->cursor_bs_valid = true;
1059 }
1060
1061 /* Set destination. */
1062 state->destination = surface;
1063 state->modified |= SMF_DESTINATION;
1064
1065 /* Set clipping region. */
1066 dfb_state_set_clip( state, &context->cursor_region );
1067
1068 /* draw cursor */
1069 unique_draw_cursor( stack, context, state, &context->cursor_region );
1070
1071 /* Reset destination. */
1072 state->destination = NULL;
1073 state->modified |= SMF_DESTINATION;
1074
1075 context->cursor_drawn = true;
1076
1077 if (restored) {
1078 if (dfb_region_region_intersects( &old_region, &context->cursor_region ))
1079 dfb_region_region_union( &old_region, &context->cursor_region );
1080 else
1081 dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT );
1082
1083 dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT );
1084 }
1085 else
1086 dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT );
1087 }
1088 else if (restored)
1089 dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT );
1090
1091 return DFB_OK;
1092 }
1093
1094