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, &region );
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