1 /* awindow.cc
2  * This file belongs to Worker, a file manager for UN*X/X11.
3  * Copyright (C) 2001-2020 Ralf Hoffmann.
4  * You can contact me at: ralf@boomerangsworld.de
5  *   or http://www.boomerangsworld.de/worker
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "awindow.h"
23 #include "text.h"
24 #include "button.h"
25 #include <list>
26 #include <algorithm>
27 #include "utf8.hh"
28 
AWindow(AGUIX * aguix,int x,int y,int width,int height,std::string title,wm_window_type_t type)29 AWindow::AWindow( AGUIX *aguix,
30 		  int x,
31 		  int y,
32 		  int width,
33 		  int height,
34 		  std::string title,
35                   wm_window_type_t type ) : Widget( aguix )
36 {
37   setIsTopLevelWidget( true );
38 
39   _x = x;
40   _y = y;
41   _w = ( width > 0 ) ? width : 1;
42   _h = ( height > 0 ) ? height : 1;
43 
44   m_open_pos_x = 0;
45   m_open_pos_y = 0;
46   m_open_max_h = false;
47   m_open_max_v = false;
48   m_force_open_position = false;
49 
50   _bg = _aguix->getFaces().getColor( "default-bg" );
51 
52   if ( _bg < 0 ) {
53       _bg = 0;
54   }
55 
56   _title = title;
57   onScreen=false;
58   border = 5;
59   win = 0;
60   doTabCycling = false;
61   forbidinput = 0;
62 #ifdef USE_XIM
63   inputcontext = NULL;
64 #endif
65   req = NULL;
66   mapNr = 0;
67   container = NULL;
68   contAutoResize = false;
69   msgW = msgH = -1;
70 
71   _callback_forbidden = false;
72 
73   m_window_type = type;
74 
75   m_size_hints = NULL;
76 }
77 
getAGUIX() const78 AGUIX *AWindow::getAGUIX() const
79 {
80   return _aguix;
81 }
82 
sizeChanged(int width,int height,bool explicit_resize)83 void AWindow::sizeChanged(int width,int height, bool explicit_resize)
84 {
85   if ( width != _w || height != _h ) {
86     AGMessage *agmsg = AGUIX_allocAGMessage();
87     agmsg->type=AG_SIZECHANGED;
88     agmsg->size.window=win;
89     agmsg->size.neww=width;
90     agmsg->size.newh=height;
91     agmsg->size.explicit_resize = explicit_resize;
92     _aguix->putAGMsg(agmsg);
93     _w = width;
94     _h = height;
95     if ( ( container != NULL ) && ( contAutoResize == true ) ) {
96       container->resize( _w, _h );
97       container->rearrange();
98     }
99   }
100 }
101 
redraw()102 void AWindow::redraw()
103 {
104   if ( _created == true ) {
105     for ( childs_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
106       (*it1)->redraw();
107     }
108   }
109 }
110 
getWindow() const111 Window AWindow::getWindow() const
112 {
113   return win;
114 }
115 
~AWindow()116 AWindow::~AWindow()
117 {
118   if ( container != NULL ) {
119     delete container;
120     container = NULL;
121   }
122   while ( _childs.size() ) {
123     delete *( _childs.begin() );
124   }
125   if ( req != NULL ) {
126     delete req;
127     req = NULL;
128   }
129   destroy();
130 }
131 
getBG() const132 int AWindow::getBG() const
133 {
134   return _bg;
135 }
136 
setBG(int tbg)137 void AWindow::setBG(int tbg)
138 {
139   _bg = tbg;
140 }
141 
ReactMessage(Message * msg)142 void AWindow::ReactMessage(Message *msg)
143 {
144   if((msg->window)!=win) return;
145   // diese Message interressiert uns
146 }
147 
setMaxSize(int mwidth,int mheight)148 void AWindow::setMaxSize(int mwidth,int mheight)
149 {
150     Display *dsp = _aguix->getDisplay();
151 
152     if ( ! m_size_hints ) {
153         m_size_hints = XAllocSizeHints();
154     }
155 
156     if ( m_size_hints ) {
157         if ( minw >= 0 ) {
158             m_size_hints->flags |= PMaxSize | PMinSize;
159             m_size_hints->min_width = minw;
160             m_size_hints->min_height = minh;
161         } else {
162             m_size_hints->flags |= PMaxSize;
163         }
164         m_size_hints->max_width = mwidth;
165         m_size_hints->max_height = mheight;
166 
167         XSetWMNormalHints( dsp, win, m_size_hints );
168     }
169 
170     maxw = mwidth;
171     maxh = mheight;
172 }
173 
setMinSize(int mwidth,int mheight)174 void AWindow::setMinSize(int mwidth,int mheight)
175 {
176     Display *dsp = _aguix->getDisplay();
177 
178     if ( ! m_size_hints ) {
179         m_size_hints = XAllocSizeHints();
180     }
181 
182     if ( m_size_hints ) {
183         if ( maxw >= 0 ) {
184             m_size_hints->flags |= PMaxSize | PMinSize;
185             m_size_hints->max_width = maxw;
186             m_size_hints->max_height = maxh;
187         } else {
188             m_size_hints->flags |= PMinSize;
189         }
190         m_size_hints->min_width = mwidth;
191         m_size_hints->min_height = mheight;
192 
193         XSetWMNormalHints( dsp, win, m_size_hints );
194     }
195 
196     minw = mwidth;
197     minh = mheight;
198 }
199 
show()200 void AWindow::show()
201 {
202   if(onScreen==true) return;
203   Display *dsp=_aguix->getDisplay();
204 
205   XMapWindow(dsp,win);
206 
207   if ( m_force_open_position &&
208        ( m_open_max_h || m_open_max_v ) ) {
209       // see
210       // https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317598336
211       XEvent ev;
212 
213       memset( &ev, 0, sizeof( ev ) );
214       ev.type = ClientMessage;
215       ev.xclient.window = win;
216       ev.xclient.message_type = _aguix->getAtom( AGUIX::NET_WM_STATE );
217       ev.xclient.format = 32;
218       ev.xclient.data.l[0] = 1;
219 
220       if ( m_open_max_h && m_open_max_v ) {
221           ev.xclient.data.l[1] = _aguix->getAtom( AGUIX::NET_WM_STATE_MAXIMIZED_HORZ );
222           ev.xclient.data.l[2] = _aguix->getAtom( AGUIX::NET_WM_STATE_MAXIMIZED_VERT );
223       } else if ( m_open_max_h ) {
224           ev.xclient.data.l[1] = _aguix->getAtom( AGUIX::NET_WM_STATE_MAXIMIZED_HORZ );
225           ev.xclient.data.l[2] = 0;
226       } else {
227           ev.xclient.data.l[1] = _aguix->getAtom( AGUIX::NET_WM_STATE_MAXIMIZED_VERT );
228           ev.xclient.data.l[2] = 0;
229       }
230 
231       ev.xclient.data.l[3] = 1;
232       XSendEvent( dsp, DefaultRootWindow( _aguix->getDisplay() ),
233                   False, SubstructureRedirectMask,
234                   &ev);
235   }
236 
237   onScreen=true;
238   _aguix->xSync();
239 }
240 
hide()241 void AWindow::hide()
242 {
243   if(onScreen==false) return;
244   Display *dsp=_aguix->getDisplay();
245   XUnmapWindow(dsp,win);
246   onScreen=false;
247 }
248 
hide(Window subwin)249 void AWindow::hide(Window subwin)
250 {
251   if(hasSubWin(subwin)==true) {
252     Display *dsp=_aguix->getDisplay();
253     XUnmapWindow(dsp,subwin);
254   }
255 }
256 
show(Window subwin)257 void AWindow::show(Window subwin)
258 {
259   if(hasSubWin(subwin)==true) {
260     Display *dsp=_aguix->getDisplay();
261     XMapWindow(dsp,subwin);
262   }
263 }
264 
getTitle() const265 const char *AWindow::getTitle() const
266 {
267   return _title.c_str();
268 }
269 
setTitle(std::string newtitle)270 void AWindow::setTitle( std::string newtitle)
271 {
272   _title = newtitle;
273   setWMTitle();
274 }
275 
resizeSubWin(Window twin,int tw,int th)276 void AWindow::resizeSubWin(Window twin,int tw,int th)
277 {
278   Display *dsp=_aguix->getDisplay();
279 
280   if ( tw < 1 ) tw = 1;
281   if ( th < 1 ) th = 1;
282 
283   XResizeWindow(dsp,twin,tw,th);
284 }
285 
moveSubWin(Window twin,int tx,int ty)286 void AWindow::moveSubWin(Window twin,int tx,int ty)
287 {
288   Display *dsp=_aguix->getDisplay();
289   XMoveWindow(dsp,twin,tx,ty);
290 }
291 
handleMessage(XEvent * E,Message * msg)292 bool AWindow::handleMessage(XEvent *E,Message *msg)
293 {
294   bool returnvalue=false;
295   int res;
296   bool conLock;
297   GUIElement *guielem;
298 
299   // continue when we own lockElement
300   conLock = false;
301   if ( msg->lockElement != NULL ) {
302     if ( contains( msg->lockElement ) == true ) conLock = true;
303   }
304 
305   //check for some input unrelated events
306   if ( ( ( msg->type == MapNotify ) &&
307          ( msg->window == win ) ) ||
308        ( ( msg->type == UnmapNotify ) &&
309          ( msg->window == win ) ) ) {
310     mapNr++;
311   }
312 
313   // return if we don't handle messages
314   if ( ( getForbidInput() == true ) &&
315        ( msg->type != Expose ) &&
316        ( msg->type != ConfigureNotify ) &&
317        ( msg->type != FocusIn ) &&
318        ( msg->type != FocusOut ) ) {
319     // but only without lockElement or we don't own it
320     if ( conLock == false ) return returnvalue;
321   }
322 
323   if ( msg->loop == 0 ) {
324     // the following code has to be executed no matter
325     // in which state the gui is so does it always but only the first loop
326     switch ( msg->type ) {
327       case FocusIn:
328 #ifdef USE_XIM
329 	if ( inputcontext != NULL ) {
330 	  if ( msg->window == win ) {
331 	    XSetICFocus( inputcontext );
332 	  }
333 	}
334 #endif
335 	if ( ( getForbidInput() == true ) && ( conLock == false ) ) return returnvalue;
336 	break;
337       case FocusOut:
338 #ifdef USE_XIM
339 	if ( inputcontext != NULL ) {
340 	  if ( msg->window == win ) {
341 	    XUnsetICFocus( inputcontext );
342 	  }
343 	}
344 #endif
345 	if ( ( getForbidInput() == true ) && ( conLock == false ) ) return returnvalue;
346 	break;
347     }
348 
349     if(msg->window==win) {
350       if(msg->type==ConfigureNotify) {
351         if ( ( msg->width != msgW ) || ( msg->height != msgH ) ) {
352           msgW = msg->width;
353           msgH = msg->height;
354           sizeChanged( msg->width, msg->height, false );
355 	}
356       }
357     }
358   }
359 
360   if ( msg->type == ConfigureNotify ) {
361       if ( getForbidInput() == true && conLock == false ) return returnvalue;
362   }
363 
364   // Alle Element bekommen Nachricht
365   res = 0;
366   for ( childs_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
367     //TODO Original wurden nur den GUIElement eine msg geschickt,
368     //     man koennte aber auch den AWindows die Msg weitergeben
369     //     und in AGUIX nur noch Toplevel anstossen
370     //     Es koennte aber Probleme machen, wenn ich bei
371     //     res == 1 abbreche
372     guielem = dynamic_cast<GUIElement*>( (*it1) );
373     if ( guielem != NULL ) {
374       res = guielem->handleMessageLock( E, msg );
375       if ( ( res == 1 ) && ( conLock == false ) ) {
376 	returnvalue = true;
377 	break;
378       }
379     }
380   }
381 
382   if ( msg->lockElement == NULL ) {
383     if ( doTabCycling == true ) {
384       if ( isParent( msg->window, false ) == true ) {
385 	if ( msg->type == KeyPress ) {
386 	  int keystate = KEYSTATEMASK( msg->keystate );
387 	  if ( ( msg->key == XK_Tab ) && ( keystate == 0 ) ) {
388 	    nextFocus();
389 	  } else if ( ( ( msg->key == XK_ISO_Left_Tab ) ||
390 			( msg->key == XK_Tab ) ) && ( keystate == ShiftMask ) ) {
391 	    // my system sends ISO_Left_Tab when tab is pressed together with ShiftMask
392 	    // so I allow normal tab key and this variant
393 	    prevFocus();
394 	  }
395 	}
396       }
397     }
398   }
399 
400   if ( msg->lockElement == NULL &&
401        msg->type == KeyPress &&
402        isTopLevel() == true &&
403        callBackForbidden() == false ) {
404     std::list<key_listener_t>::iterator it;
405     AGMessage *agmsg = AGUIX_allocAGMessage( msg );
406 
407     for ( it = key_listener.begin(); it != key_listener.end(); it++ ) {
408       //TODO pruefen, ob subwin ue1berhautp ein subwin von this is, also recursiv alle childs pruefen
409       if ( ( (*it).mode & KEYCB_WHENVISIBLE ) == 0 || (*it).subwin->isVisible() == true ) {
410         forbidCallBacks();
411         (*it).cb->run( (*it).subwin, *agmsg );
412         permitCallBacks();
413       }
414     }
415     AGUIX_freeAGMessage( agmsg );
416   }
417 
418   return returnvalue;
419 }
420 
hasSubWin(Window twin) const421 bool AWindow::hasSubWin(Window twin) const
422 {
423   std::list<Window>::const_iterator it1;
424 
425   it1 = std::find( subwins.begin(), subwins.end(), twin );
426   if ( it1 == subwins.end() ) return false;
427   return true;
428 }
429 
getSubWindow(Window parent,int tx,int ty,int tw,int th)430 Window AWindow::getSubWindow(Window parent,int tx,int ty,int tw,int th)
431 {
432   Window newwin,pwin;
433   Display *dsp=_aguix->getDisplay();
434   int scr=_aguix->getScreen();
435   Visual *vis=DefaultVisual(dsp,scr);
436   unsigned long mask=CWEventMask|CWBackPixel|CWColormap;
437 
438   if ( tw < 1 ) tw = 1;
439   if ( th < 1 ) th = 1;
440 
441   XSetWindowAttributes attr;
442   attr.event_mask=ExposureMask|ButtonPressMask|ButtonReleaseMask|StructureNotifyMask|KeyPressMask|KeyReleaseMask|ButtonMotionMask|EnterWindowMask|LeaveWindowMask|PointerMotionHintMask;
443   attr.background_pixel=_aguix->getPixel(_bg);
444   attr.colormap=_aguix->getColormap();
445 
446   if ( ( parent != 0 ) && ( hasSubWin( parent ) == true ) )
447     pwin = parent;
448   else
449     pwin = win;
450 
451   newwin=XCreateWindow(dsp,pwin,tx,ty,tw,th,0,_aguix->getDepth(),InputOutput,vis,mask,&attr);
452   if(!newwin) {
453     return newwin;
454   }
455   XMapRaised(dsp,newwin);
456   XClearWindow(dsp,newwin);
457   subwins.push_back( newwin );
458   return newwin;
459 }
460 
removeSubWin(Window subwin)461 void AWindow::removeSubWin(Window subwin)
462 {
463   if(hasSubWin(subwin)==true) {
464     Display *dsp=_aguix->getDisplay();
465     XDestroyWindow(dsp,subwin);
466     subwins.remove( subwin );
467   }
468 }
469 
isParent(Window childwin,bool direct) const470 bool AWindow::isParent(Window childwin,bool direct) const
471 {
472   bool found = false;
473   AWindow *twin;
474 
475   if ( direct == false ) {
476     for ( childs_const_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
477       twin = dynamic_cast<AWindow*>( (*it1) );
478       if ( twin != NULL ) {
479           if ( twin->isParent( childwin, false ) == true ) {
480               found = true;
481               break;
482           }
483       }
484     }
485   }
486   if ( found == false && hasSubWin( childwin ) == true ) found = true;
487   if ( childwin == win ) found = true;
488   return found;
489 }
490 
isParent(Window childwin) const491 bool AWindow::isParent( Window childwin ) const
492 {
493   return isParent( childwin, true );
494 }
495 
move(int nx,int ny)496 void AWindow::move(int nx,int ny)
497 {
498   Display *dsp=_aguix->getDisplay();
499   XMoveWindow(dsp,win,nx,ny);
500   _x = nx;
501   _y = ny;
502 }
503 
resize(int nw,int nh)504 void AWindow::resize(int nw,int nh)
505 {
506   int newminw, newminh, newmaxw, newmaxh;
507 
508   if ( ( nw > 0 ) && ( nh > 0 ) ) {
509     if ( ( nw != _w ) || ( nh != _h ) ) {
510       Display *dsp=_aguix->getDisplay();
511 
512       // first check if we doesn't crash with the min/maxwidths
513       // some WMs doesn't allow resize in this case (atleast KWM)
514       if ( minw > 0 ) {
515 	newminw = ( nw < minw ) ? nw : minw;
516 	newminh = ( nh < minh ) ? nh : minh;
517 	if ( ( newminw != minw ) || ( newminh != minh ) ) {
518 	  setMinSize( newminw, newminh );
519 	}
520       }
521       if ( maxw > 0 ) {
522 	newmaxw = ( nw > maxw ) ? nw : maxw;
523 	newmaxh = ( nh > maxh ) ? nh : maxh;
524 	if ( ( newmaxw != maxw ) || ( newmaxh != maxh ) ) {
525 	  setMaxSize( newmaxw, newmaxh );
526 	}
527       }
528 
529       XResizeWindow(dsp,win,nw,nh);
530 #if 0
531       // it's possible to not call sizeChanged here
532       // but the size has to be stored so if one use
533       // this case, the test in sizeChanged for different size
534       // has to be removed because it would be always true in the
535       // manual resize case
536       _w = nw;
537       _h = nh;
538 #else
539       sizeChanged( nw, nh, true );
540 #endif
541     }
542   }
543 }
544 
findWidgetForWindow(Window child)545 Widget *AWindow::findWidgetForWindow( Window child )
546 {
547   childs_const_it it1;
548 
549   for ( it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
550     if ( (*it1)->isParent( child ) == true ) break;
551   }
552   if ( it1 == _childs.end() ) return NULL;
553   return *it1;
554 }
555 
setCursor(int type)556 void AWindow::setCursor(int type)
557 {
558   _aguix->setCursor(win,type);
559 }
560 
unsetCursor()561 void AWindow::unsetCursor()
562 {
563   _aguix->unsetCursor(win);
564 }
565 
invalidFocus()566 void AWindow::invalidFocus()
567 {
568   Focus *f;
569   Widget *w;
570 
571   // we could had a focus owner before getting a parent awindow
572   // so first check if we have not one
573   if(_parent!=NULL) {
574     _parent->invalidFocus();
575   }
576   // if we have a focus owner, release it
577   f = getFocusElement( this );
578   if ( f != NULL ) {
579     setFocusElement( this, NULL );
580     w = dynamic_cast<Widget*>( f );
581     if ( w != NULL )
582       w->redraw();
583   }
584 }
585 
applyFocus(Widget * newfocus)586 void AWindow::applyFocus( Widget *newfocus )
587 {
588   if ( ( newfocus != NULL ) && ( isOwner( newfocus ) == true ) ) return;
589 
590   invalidFocus();
591   if ( newfocus != NULL ) {
592     if ( _parent != NULL ) {
593       _parent->applyFocus( newfocus );
594     } else {
595       setFocusElement( this, newfocus );
596       newfocus->redraw();
597     }
598   }
599 }
600 
isOwner(Widget * f) const601 bool AWindow::isOwner( Widget *f ) const
602 {
603   if(_parent!=NULL) {
604     return _parent->isOwner(f);
605   } else {
606     if ( getFocusElement( this ) == f ) return true;
607   }
608   return false;
609 }
610 
maximizeX()611 void AWindow::maximizeX()
612 {
613   int mw,tw;
614 
615   mw = 0;
616 
617   for ( childs_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
618     tw = (*it1)->getX() + (*it1)->getWidth() + border;
619     if ( tw > mw )
620       mw = tw;
621   }
622   if ( mw > _w ) {
623     resize( mw, _h );
624   }
625 }
626 
maximizeY()627 void AWindow::maximizeY()
628 {
629   int mh,th;
630 
631   mh = 0;
632   for ( childs_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
633     th = (*it1)->getY() + (*it1)->getHeight() + border;
634     if ( th > mh )
635       mh = th;
636   }
637   if ( mh > _h ) {
638     resize( _w, mh );
639   }
640 }
641 
getBorderWidth() const642 int AWindow::getBorderWidth() const
643 {
644   return border;
645 }
646 
setBorderWidth(int nv)647 void AWindow::setBorderWidth( int nv )
648 {
649   if ( ( nv < 0 ) ||
650        ( nv >= _w/2 ) ) return;
651   border = nv;
652 }
653 
addTextFromString(const char * text,int tx,int ty,int vspace,Text *** return_texts,int * return_count,int * return_y)654 int AWindow::addTextFromString( const char *text,
655 				int tx,
656 				int ty,
657 				int vspace,
658 				Text ***return_texts,
659 				int *return_count,
660 				int *return_y )
661 {
662   int i;
663   int lines;
664   char **liness;
665   Text **text_elems;
666 
667   if ( text == NULL ) return 1;
668 
669   if ( tx < 0 ) tx = 0;
670   if ( ty < 0 ) ty = 0;
671   if ( vspace < 0 ) vspace = 0;
672 
673   lines = createLines( text, &liness );
674 
675   text_elems = (Text**)_allocsafe( sizeof( Text* ) * lines );
676 
677   for ( i = 0; i < lines; i++ ) {
678     text_elems[i] = (Text*)add( new Text( _aguix, tx, ty, liness[i] ) );
679     ty += text_elems[i]->getHeight() + vspace;
680   }
681 
682   if ( return_texts != NULL ) {
683     // caller want the Text list
684     *return_texts = text_elems;
685   } else _freesafe( text_elems );
686 
687   if ( return_count != NULL ) {
688     *return_count = lines;
689   }
690 
691   if ( return_y != NULL ) {
692     // ty is not the real y value because vspace is always added
693     *return_y = ty - vspace;
694   }
695 
696   for ( i = 0; i < lines; i++ ) _freesafe( liness[i] );
697   _freesafe( liness );
698 
699   return 0;
700 }
701 
addMultiLineText(const std::string text,AContainer & ac,int xpos,int ypos,AContainer ** return_container,std::list<Text * > * return_text_list,bool split_on_newline)702 int AWindow::addMultiLineText( const std::string text,
703                                AContainer &ac,
704                                int xpos, int ypos,
705                                AContainer **return_container,
706                                std::list<Text*> *return_text_list,
707                                bool split_on_newline )
708 {
709   int i;
710   int lines;
711   char **liness;
712   Text *textelement;
713 
714   if ( split_on_newline ) {
715       lines = createLines( text.c_str(), &liness, '\n' );
716   } else {
717       lines = createLines( text.c_str(), &liness );
718   }
719 
720   AContainer *textac = ac.add( new AContainer( this, 1, lines ), xpos, ypos );
721   textac->setMinSpace( 5 );
722   textac->setMaxSpace( 5 );
723   textac->setBorderWidth( 0 );
724 
725   for ( i = 0; i < lines; i++ ) {
726     textelement = (Text*)textac->add( new Text( _aguix, 0, 0, liness[i] ),
727                                       0, i, AContainer::CO_INCWNR );
728     if ( return_text_list != NULL ) {
729       return_text_list->push_back( textelement );
730     }
731   }
732 
733   for ( i = 0; i < lines; i++ ) _freesafe( liness[i] );
734   _freesafe( liness );
735 
736   if ( return_container != NULL ) *return_container = textac;
737   return 0;
738 }
739 
centerScreen()740 void AWindow::centerScreen()
741 {
742   int rw, rh, nx, ny;
743 
744   _aguix->getLargestDimensionOfCurrentScreen( NULL, NULL, &rw, &rh );
745 
746   if ( ( rw < 1 ) || ( rh < 1 ) ) return;
747 
748   nx = ( rw / 2 ) - ( _w / 2 );
749   ny = ( rh / 2 ) - ( _h / 2 );
750   move( nx, ny );
751 }
752 
contains(Widget * elem) const753 bool AWindow::contains( Widget *elem ) const
754 {
755   bool returnvalue = false;
756   AWindow *twin;
757 
758   for ( childs_const_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
759     if ( (*it1) == elem ) {
760       returnvalue = true;
761       break;
762     }
763   }
764   if ( returnvalue == false ) {
765     for ( childs_const_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
766       twin = dynamic_cast<AWindow*>( (*it1) );
767       if ( twin != NULL ) {
768 	if ( twin->contains( elem ) == true ) {
769 	  returnvalue = true;
770 	  break;
771 	}
772       }
773     }
774   }
775   return returnvalue;
776 }
777 
getFocusOwner() const778 Widget *AWindow::getFocusOwner() const
779 {
780   Focus *f;
781 
782   if ( _parent != NULL )
783     return _parent->getFocusOwner();
784   f = getFocusElement( this );
785   if ( f == NULL ) return NULL;
786   return dynamic_cast<Widget*>( f );
787 }
788 
nextFocus()789 void AWindow::nextFocus()
790 {
791   Widget *tw, *next;
792   Focus *f;
793 
794   if ( _parent != NULL ) {
795     _parent->nextFocus();
796   } else {
797 
798     f = getFocusElement( this );
799     tw = dynamic_cast<Widget*>( f );
800     next = searchNextFocus( tw );
801 
802     if ( next != NULL ) {
803       applyFocus( next );
804     }
805   }
806 }
807 
prevFocus()808 void AWindow::prevFocus()
809 {
810   Widget *tw, *prev;
811   Focus *f;
812 
813   if ( _parent != NULL ) {
814     _parent->prevFocus();
815   } else {
816 
817     f = getFocusElement( this );
818     tw = dynamic_cast<Widget*>( f );
819     prev = searchPrevFocus( tw );
820 
821     if ( prev != NULL ) {
822       applyFocus( prev );
823     }
824   }
825 }
826 
setDoTabCycling(bool nv)827 void AWindow::setDoTabCycling( bool nv )
828 {
829   doTabCycling = nv;
830 }
831 
getDoTabCycling() const832 bool AWindow::getDoTabCycling() const
833 {
834   return doTabCycling;
835 }
836 
isTopParent(Window childwin)837 bool AWindow::isTopParent( Window childwin )
838 {
839   if ( _parent != NULL )
840     return _parent->isTopParent( childwin );
841   else
842     return isParent( childwin, false );
843 }
844 
isVisible() const845 bool AWindow::isVisible() const
846 {
847   if ( onScreen == false ) return false;
848   else {
849     if ( _parent != NULL ) {
850       if ( _parent->isVisible() == true ) return true;
851       else return false;
852     } else {
853       return true;
854     }
855   }
856 }
857 
useStippleBackground()858 void AWindow::useStippleBackground()
859 {
860   _aguix->setWindowBackgroundPixmap( win );
861 }
862 
forbidUserInput()863 void AWindow::forbidUserInput()
864 {
865   forbidinput++;
866 }
867 
permitUserInput()868 void AWindow::permitUserInput()
869 {
870   forbidinput--;
871   if ( forbidinput < 0 ) forbidinput = 0;
872 }
873 
getForbidInput() const874 bool AWindow::getForbidInput() const
875 {
876   if ( _parent != NULL )
877     return _parent->getForbidInput();
878   else
879     return ( forbidinput == 0 ) ? false : true;
880 }
881 
setTransientForAWindow(const AWindow * twin)882 void AWindow::setTransientForAWindow( const AWindow *twin )
883 {
884   if ( win == 0 ) return;
885   if ( twin == NULL ) {
886     XSetTransientForHint( _aguix->getDisplay(), getWindow(), None );
887   } else {
888     XSetTransientForHint( _aguix->getDisplay(), getWindow(), twin->getWindow() );
889   }
890 }
891 
892 #ifdef USE_XIM
getXIC() const893 XIC AWindow::getXIC() const
894 {
895   return inputcontext;
896 }
897 
createXIC()898 int AWindow::createXIC()
899 {
900   long im_event_mask;
901   XWindowAttributes attr;
902 
903   if ( _parent != NULL ) {
904     inputcontext = NULL;
905     return 0;
906   }
907 
908   if ( ( _aguix->getXIM() != NULL ) && ( _aguix->getXIMStyle() != 0 ) ) {
909     _aguix->Flush();
910     inputcontext = XCreateIC( _aguix->getXIM(),
911 			      XNInputStyle, _aguix->getXIMStyle(),
912 			      XNClientWindow, win,
913 			      (void*)NULL );
914     if ( inputcontext == NULL ) {
915       fprintf( stderr, "Worker Warning: Cannot create input context\n");
916     } else {
917       XGetICValues( inputcontext, XNFilterEvents, &im_event_mask, (void*)NULL );
918       XGetWindowAttributes( _aguix->getDisplay(), win, &attr );
919       XSelectInput( _aguix->getDisplay(), win, attr.your_event_mask | im_event_mask );
920     }
921   } else {
922     inputcontext = NULL;
923   }
924   return ( ( inputcontext != NULL ) ? 0 : 1 );
925 }
926 
closeXIC()927 void AWindow::closeXIC()
928 {
929   if ( inputcontext != NULL ) {
930     XDestroyIC( inputcontext );
931     inputcontext = NULL;
932   }
933 }
934 
XICdestroyed()935 void AWindow::XICdestroyed()
936 {
937   inputcontext = NULL;
938 }
939 
940 #endif
941 
isTopLevel() const942 bool AWindow::isTopLevel() const
943 {
944   return ( ( _parent == NULL ) ? true : false );
945 }
946 
request(const char * reqtitle,const char * text,const char * buttons,Requester::request_flags_t flags)947 int AWindow::request( const char *reqtitle, const char *text, const char *buttons, Requester::request_flags_t flags )
948 {
949   if ( _parent != NULL ) {
950     return _parent->request( reqtitle, text, buttons, flags );
951   }
952 
953   if ( req == NULL ) {
954     req = new Requester( _aguix, this );
955   }
956   return req->request( reqtitle, text, buttons, flags );
957 }
958 
string_request(const char * reqtitle,const char * lines,const char * default_str,const char * buttons,char ** return_str,Requester::request_flags_t flags)959 int AWindow::string_request( const char *reqtitle, const char *lines, const char *default_str, const char *buttons, char **return_str, Requester::request_flags_t flags )
960 {
961   if ( _parent != NULL ) {
962     return _parent->string_request( reqtitle, lines, default_str, buttons, return_str, flags );
963   }
964 
965   if ( req == NULL ) {
966     req = new Requester( _aguix, this );
967   }
968   return req->string_request( reqtitle, lines, default_str, buttons, return_str, flags );
969 }
970 
getMapNr() const971 int AWindow::getMapNr() const
972 {
973   return mapNr;
974 }
975 
setContainer(AContainer * newcont,bool autoResize)976 AContainer *AWindow::setContainer( AContainer *newcont, bool autoResize )
977 {
978   container = newcont;
979   contAutoResize = autoResize;
980   return newcont;
981 }
982 
removeContainer(AContainer * cont)983 void AWindow::removeContainer( AContainer *cont )
984 {
985   if ( container == cont ) {
986     container = NULL;
987   }
988 }
989 
removeFromContainer(Widget * twid)990 void AWindow::removeFromContainer( Widget *twid )
991 {
992   if ( container != NULL ) {
993     container->remove( twid );
994   }
995 }
996 
contMaximize(bool applyMinSize,bool applyMaxSize)997 void AWindow::contMaximize( bool applyMinSize, bool applyMaxSize )
998 {
999   int tw, th;
1000 
1001   if ( container != NULL ) {
1002     // to maximize the window get the min width/height for
1003     // the container by resizing to 0,0 and finally add position
1004     container->resize( 0, 0 );
1005     container->rearrange();
1006     tw = container->getWidth();
1007     th = container->getHeight();
1008     tw += container->getX();
1009     th += container->getY();
1010     if ( applyMinSize == true ) setMinSize( tw, th );
1011     if ( applyMaxSize == true ) setMaxSize( tw, th );
1012     resize( tw, th );
1013   }
1014 }
1015 
doCreateStuff()1016 void AWindow::doCreateStuff()
1017 {
1018   Display *dsp = _aguix->getDisplay();
1019   Window ParentWnd;
1020   int scr;
1021   Visual *vis;
1022   unsigned long mask = CWEventMask | CWBackPixel | CWColormap;
1023   XSetWindowAttributes attr;
1024   XWMHints *WMHints;
1025 
1026   scr = _aguix->getScreen();
1027   vis = DefaultVisual( dsp, scr );
1028 
1029   if ( _parent == NULL ) {
1030     ParentWnd = RootWindow( dsp, scr );
1031   } else {
1032     ParentWnd = _parent->win;
1033   }
1034 
1035   attr.event_mask =
1036     ExposureMask |
1037     ButtonPressMask |
1038     ButtonReleaseMask |
1039     StructureNotifyMask |
1040     KeyPressMask |
1041     KeyReleaseMask |
1042     ButtonMotionMask |
1043     PointerMotionHintMask |
1044     FocusChangeMask;
1045   attr.background_pixel = _aguix->getPixel( _bg );
1046   attr.colormap = _aguix->getColormap();
1047 
1048   // create window
1049   win = XCreateWindow( dsp, ParentWnd,
1050                        m_force_open_position ? m_open_pos_x : _x,
1051                        m_force_open_position ? m_open_pos_y : _y,
1052                        _w, _h, 0, _aguix->getDepth(), InputOutput, vis, mask, &attr );
1053   if ( !win ) {
1054     return;
1055   }
1056 
1057   maxw = -1;
1058   maxh = -1;
1059   minw = -1;
1060   minh = -1;
1061 
1062   // now set advanced window attributes (for window managers...)
1063   setWMTitle();
1064 
1065   // for close button
1066   XSetWMProtocols( dsp, win, _aguix->getCloseAtom(), 1 );
1067 
1068   // size of the window
1069   if ( ! m_size_hints ) {
1070       m_size_hints = XAllocSizeHints();
1071   }
1072 
1073   if ( m_size_hints ) {
1074       m_size_hints->flags = PSize;
1075       m_size_hints->width = _w;
1076       m_size_hints->height = _h;
1077 
1078       if ( m_force_open_position ) {
1079           m_size_hints->flags |= USPosition;
1080 
1081           m_size_hints->x = m_open_pos_x;
1082           m_size_hints->y = m_open_pos_y;
1083       }
1084 
1085       XSetWMNormalHints( dsp, win, m_size_hints );
1086   }
1087 
1088   // window grouping for window managers
1089   WMHints = XAllocWMHints();
1090   if ( WMHints ) {
1091       WMHints->input = True;
1092       WMHints->window_group = _aguix->getGroupWin();
1093       WMHints->flags = InputHint | WindowGroupHint;
1094       XSetWMHints( dsp, win, WMHints );
1095       XFree( WMHints );
1096   }
1097 
1098   // command so the window manager can restart worker
1099   XSetCommand( dsp, win, _aguix->getargv(), _aguix->getargc() );
1100 
1101   if ( _aguix->getApplyWindowDialogType() ) {
1102       Atom window_type_atom;
1103 
1104       if ( m_window_type == AWINDOW_DIALOG ) {
1105           window_type_atom = _aguix->getAtom( AGUIX::NET_WM_WINDOW_TYPE_DIALOG );
1106       } else {
1107           window_type_atom = _aguix->getAtom( AGUIX::NET_WM_WINDOW_TYPE_NORMAL );
1108       }
1109 
1110       XChangeProperty( dsp, win,
1111                        _aguix->getAtom( AGUIX::NET_WM_WINDOW_TYPE ),
1112                        XA_ATOM, 32, PropModeReplace, (unsigned char *) &window_type_atom, 1 );
1113   }
1114 
1115   if ( m_window_type == AWINDOW_DIALOG ) {
1116       const AWindow *twin = _aguix->getTransientWindow();
1117 
1118       if ( twin ) {
1119           setTransientForAWindow( twin );
1120       }
1121   }
1122 
1123   applyIcon();
1124 
1125   // clear window
1126   XClearWindow( dsp, win );
1127 
1128   // insert window into _aguix
1129   if ( m_window_type == AWINDOW_DIALOG ) {
1130       _aguix->insertWindow( this, false );
1131   } else {
1132       _aguix->insertWindow( this, true );
1133   }
1134 
1135 #ifdef USE_XIM
1136   // create xinput stuff
1137   createXIC();
1138 #endif
1139   Widget::doCreateStuff();
1140 
1141   _aguix->Flush();
1142   return;
1143 }
1144 
doDestroyStuff()1145 void AWindow::doDestroyStuff()
1146 {
1147   if ( _created == true ) {
1148     Display *dsp=_aguix->getDisplay();
1149     _aguix->removeWindow( this );
1150 
1151 #ifdef WMDESTROYBUGFIX
1152     if ( _parent == NULL ) {
1153       _aguix->Flush();
1154       XSync( dsp, False );
1155       waittime( 10 );
1156     }
1157 #endif
1158 #ifdef USE_XIM
1159     closeXIC();
1160 #endif
1161     if ( win != 0 ) {
1162       XDestroyWindow( dsp, win );
1163       win = 0;
1164     }
1165     _aguix->Flush();
1166 
1167     if ( m_size_hints ) {
1168         XFree( m_size_hints );
1169         m_size_hints = NULL;
1170     }
1171   }
1172 
1173   onScreen = false;
1174   _title = "";
1175   Widget::doDestroyStuff();
1176 }
1177 
remove(Widget * w)1178 void AWindow::remove( Widget *w )
1179 {
1180   std::list<Widget*>::iterator it1;
1181   Widget *focusw;
1182 
1183   if ( w == NULL ) return;
1184 
1185   it1 = std::find( _childs.begin(), _childs.end(), w );
1186   if ( it1 == _childs.end() ) return; // not found
1187 
1188   if ( _created == true ) w->destroy();
1189   focusw = getFocusOwner();
1190   if ( focusw != NULL ) {
1191     // check if the child has the focusowner
1192     if ( w->contains( focusw ) == true ) {
1193       invalidFocus();
1194     }
1195   }
1196   if ( container != NULL ) removeFromContainer( w );
1197   if ( _parent != NULL ) _parent->removeFromContainer( w );
1198   w->setParent( NULL );
1199   _childs.remove( w );
1200 }
1201 
create()1202 int AWindow::create()
1203 {
1204   std::list<Widget*>::iterator it1;
1205   int res;
1206 
1207   res = Widget::create();
1208   if ( _created == true ) {
1209     for ( it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
1210       (*it1)->create();
1211     }
1212   }
1213   return res;
1214 }
1215 
destroy()1216 void AWindow::destroy()
1217 {
1218   std::list<Widget*>::iterator it1;
1219 
1220   if ( _parent != NULL ) {
1221     _parent->removeKeyCallBack( this, NULL );
1222   }
1223 
1224   if ( _created == true ) {
1225     for ( it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
1226       (*it1)->destroy();
1227     }
1228   }
1229   Widget::destroy();
1230 }
1231 
setParent(class AWindow * parent)1232 int AWindow::setParent( class AWindow *parent )
1233 {
1234   // do not accept parent if already created
1235   //TODO it would be possible to destroy the window in
1236   // this case and reopen it
1237   if ( _created == true ) return 1;
1238   //TODO Wenn das Fenster schon ein Fokuselement haelt,
1239   //     Dann sollte es dem parent uebergeben werden
1240   return Widget::setParent( parent );
1241 }
1242 
setWMTitle()1243 int AWindow::setWMTitle()
1244 {
1245   Display *dsp;
1246   XClassHint classhint;
1247   XTextProperty windowname;
1248   char *tstr;
1249 
1250   dsp = _aguix->getDisplay();
1251   if ( ( dsp == NULL ) || ( win == 0 ) ) return 1;
1252 
1253   classhint.res_name = dupstring( _title.c_str() );
1254   classhint.res_class = dupstring( _aguix->getClassname().c_str() );
1255   XSetClassHint( dsp, win, &classhint );
1256   _freesafe( classhint.res_class );
1257   _freesafe( classhint.res_name );
1258 
1259   tstr = dupstring( _title.c_str() );
1260 
1261   if ( XStringListToTextProperty( &tstr, 1, &windowname ) != 0 ) {
1262       XTextProperty ticonname;
1263       if ( XStringListToTextProperty( &tstr, 1, &ticonname ) != 0 ) {
1264           XSetWMName( dsp, win, &windowname );
1265           XSetWMIconName( dsp, win, &ticonname );
1266           XFree( ticonname.value );
1267       }
1268       XFree( windowname.value );
1269   }
1270 
1271 #if defined( X_HAVE_UTF8_STRING ) && !defined( DISABLE_UTF8_SUPPORT )
1272   if ( UTF8::getUTF8Mode() != UTF8::UTF8_DISABLED && UTF8::getCurrentEncoding() == UTF8::ENCODING_UTF8 ) {
1273       XTextProperty utf8name;
1274 
1275       if ( XmbTextListToTextProperty( dsp, &tstr, 1, XUTF8StringStyle, &utf8name ) == Success ) {
1276           XSetTextProperty( dsp, win, &utf8name, _aguix->getAtom( AGUIX::NET_WM_NAME_ATOM ) );
1277           XSetTextProperty( dsp, win, &utf8name, _aguix->getAtom( AGUIX::NET_WM_ICON_NAME_ATOM ) );
1278           XFree( utf8name.value );
1279       }
1280   }
1281 #endif
1282 
1283   _freesafe( tstr );
1284 
1285   XStoreName( dsp, win, _title.c_str() );
1286 
1287   return 0;
1288 }
1289 
getChilds() const1290 const std::list<Widget*> &AWindow::getChilds() const
1291 {
1292   return _childs;
1293 }
1294 
searchNextFocus(focus_search_mode_t & search_mode,const Widget * element,Widget ** new_element,Widget ** prev_element)1295 int AWindow::searchNextFocus( focus_search_mode_t &search_mode,
1296 			      const Widget *element,
1297 			      Widget **new_element,
1298 			      Widget **prev_element )
1299 {
1300   AWindow *twin;
1301 
1302   if ( search_mode == SEARCH_FINISHED ) {
1303     return 0;
1304   } else if ( ( search_mode == SEARCH_NEXT ) && ( getAcceptFocus() == true ) && ( isVisible() == true ) ) {
1305     *new_element = this;
1306     search_mode = SEARCH_FINISHED;
1307   } else {
1308     if ( ( search_mode == SEARCH_WIDGET ) && ( this == element ) ) search_mode = SEARCH_NEXT;
1309     else if ( ( search_mode == SEARCH_WIDGET ) &&
1310 	      ( this != element ) &&
1311 	      ( prev_element != NULL ) &&
1312 	      ( getAcceptFocus() == true ) &&
1313 	      ( isVisible() == true ) )
1314       *prev_element = this;
1315 
1316     for ( childs_it it1 = _childs.begin(); it1 != _childs.end(); it1++ ) {
1317       twin = dynamic_cast<AWindow*>( (*it1) );
1318       if ( twin != NULL ) {
1319 	twin->searchNextFocus( search_mode, element, new_element, prev_element );
1320       } else {
1321 	if ( ( search_mode == SEARCH_WIDGET ) && ( (*it1) == element ) ) search_mode = SEARCH_NEXT;
1322 	else if ( ( search_mode == SEARCH_WIDGET ) &&
1323 		  ( (*it1) != element ) &&
1324 		  ( prev_element != NULL ) &&
1325 		  ( (*it1)->getAcceptFocus() == true ) &&
1326 		  ( (*it1)->isVisible() == true ) ) *prev_element = (*it1);
1327 	else if ( ( search_mode == SEARCH_NEXT ) && ( (*it1)->getAcceptFocus() == true ) && ( (*it1)->isVisible() == true ) ) {
1328 	  *new_element = (*it1);
1329 	  search_mode = SEARCH_FINISHED;
1330 	}
1331       }
1332       if ( search_mode == SEARCH_FINISHED ) break;
1333     }
1334   }
1335   return 0;
1336 }
1337 
searchNextFocus(const Widget * current)1338 Widget *AWindow::searchNextFocus( const Widget *current )
1339 {
1340   focus_search_mode_t mode = SEARCH_WIDGET;
1341   Widget *new_element = NULL;
1342 
1343   if ( current == NULL ) mode = SEARCH_NEXT;
1344   searchNextFocus( mode, current, &new_element );
1345 
1346   if ( new_element == NULL ) {
1347     // no new focus element found
1348     // start again with mode NEXT
1349     mode = SEARCH_NEXT;
1350     searchNextFocus( mode, current, &new_element );
1351   }
1352 
1353   // return element
1354   // it it is NULL it just means there is no focus element
1355   return new_element;
1356 }
1357 
searchPrevFocus(const Widget * current)1358 Widget *AWindow::searchPrevFocus( const Widget *current )
1359 {
1360   focus_search_mode_t mode = SEARCH_WIDGET;
1361   Widget *new_element = NULL, *prev_element = NULL;
1362 
1363   if ( current == NULL ) mode = SEARCH_NEXT;
1364   searchNextFocus( mode, current, &new_element, &prev_element );
1365 
1366   if ( prev_element == NULL ) {
1367     // no prev found so start again with NULL element which
1368     // will go through all elements and should return the last
1369     // which is the only one which can not be found by the
1370     // first run
1371     mode = SEARCH_WIDGET;
1372     searchNextFocus( mode, NULL, &new_element, &prev_element );
1373   }
1374 
1375   // return element
1376   // it it is NULL it just means there is no focus element
1377   return prev_element;
1378 }
1379 
addWindowEvent(Window subwin,long mask)1380 int AWindow::addWindowEvent( Window subwin, long mask )
1381 {
1382   XWindowAttributes curattr;
1383 
1384   if ( hasSubWin( subwin ) == false )
1385     return 1;
1386 
1387   XGetWindowAttributes( _aguix->getDisplay(), subwin, &curattr );
1388   XSelectInput( _aguix->getDisplay(), subwin, curattr.your_event_mask | mask );
1389   return 0;
1390 }
1391 
getMinWidth() const1392 int AWindow::getMinWidth() const
1393 {
1394   return minw;
1395 }
1396 
getMinHeight() const1397 int AWindow::getMinHeight() const
1398 {
1399   return minh;
1400 }
1401 
getMaxWidth() const1402 int AWindow::getMaxWidth() const
1403 {
1404   return maxw;
1405 }
1406 
getMaxHeight() const1407 int AWindow::getMaxHeight() const
1408 {
1409   return maxh;
1410 }
1411 
addKeyCallBack(CallBack * new_cb,int mode)1412 void AWindow::addKeyCallBack( CallBack *new_cb, int mode )
1413 {
1414   addKeyCallBack( this, new_cb, mode );
1415 }
1416 
addKeyCallBack(AWindow * subwin,CallBack * new_cb,int mode)1417 void AWindow::addKeyCallBack( AWindow *subwin, CallBack *new_cb, int mode )
1418 {
1419   if ( _parent != NULL ) {
1420     _parent->addKeyCallBack( subwin, new_cb, mode );
1421   } else {
1422     key_listener_t k;
1423 
1424     k.cb = new_cb;
1425     k.subwin = subwin;
1426     k.mode = mode;
1427     key_listener.push_back( k );
1428   }
1429 }
1430 
removeKeyCallBack(AWindow * subwin,CallBack * cb)1431 void AWindow::removeKeyCallBack( AWindow *subwin, CallBack *cb )
1432 {
1433   if ( _parent != NULL ) {
1434     _parent->removeKeyCallBack( subwin, cb );
1435   } else {
1436     std::list<key_listener_t>::iterator it;
1437 
1438     for ( it = key_listener.begin(); it != key_listener.end(); it++ ) {
1439       if ( (*it).subwin == subwin )  {
1440         if ( cb == NULL || (*it).cb == cb ) {
1441           it = key_listener.erase( it );
1442         }
1443       }
1444     }
1445   }
1446 }
1447 
removeKeyCallBack(CallBack * cb)1448 void AWindow::removeKeyCallBack( CallBack *cb )
1449 {
1450   if ( cb == NULL ) return;  // removal  of all callbacks are not allowed from public interface
1451 
1452   removeKeyCallBack( this, cb );
1453 }
1454 
forbidCallBacks()1455 void AWindow::forbidCallBacks()
1456 {
1457   _callback_forbidden = true;
1458   if ( _parent != NULL ) _parent->forbidCallBacks();
1459 }
1460 
permitCallBacks()1461 void AWindow::permitCallBacks()
1462 {
1463   if ( _parent != NULL ) _parent->permitCallBacks();
1464   _callback_forbidden = false;
1465 }
1466 
callBackForbidden() const1467 bool AWindow::callBackForbidden() const
1468 {
1469   if ( _callback_forbidden == true ) return true;
1470   if ( _parent != NULL ) return _parent->callBackForbidden();
1471   return false;
1472 }
1473 
toFront()1474 void AWindow::toFront()
1475 {
1476     if ( _created == false ) return;
1477     _aguix->WindowtoFront( win );
1478 }
1479 
updateCont()1480 void AWindow::updateCont()
1481 {
1482     if ( container != NULL ) {
1483         container->resize( getWidth(), getHeight() );
1484         container->rearrange();
1485     }
1486 }
1487 
isMaximized()1488 int AWindow::isMaximized()
1489 {
1490     Atom ret_type;
1491     int ret_format;
1492     unsigned long ret_len,ret_after;
1493     unsigned char *ret_prop;
1494 
1495     int res = 0;
1496 
1497     if ( _created == false ) return res;
1498 
1499     if ( XGetWindowProperty( _aguix->getDisplay(),
1500                              win,
1501                              _aguix->getAtom( AGUIX::NET_WM_STATE ),
1502                              0,
1503                              32,
1504                              False,
1505                              AnyPropertyType,
1506                              &ret_type,
1507                              &ret_format,
1508                              &ret_len,
1509                              &ret_after,
1510                              &ret_prop ) == Success ) {
1511         if ( ret_len > 0 &&
1512              ret_type == XA_ATOM &&
1513              ret_format == 32 ) {
1514             const Atom *atoms = (const Atom*)ret_prop;
1515             for ( unsigned long i = 0; i < ret_len; i++ ) {
1516                 if ( atoms[i] == _aguix->getAtom( AGUIX::NET_WM_STATE_MAXIMIZED_HORZ ) ) {
1517                     res |= 1;
1518                 } else if ( atoms[i] == _aguix->getAtom( AGUIX::NET_WM_STATE_MAXIMIZED_VERT ) ) {
1519                     res |= 2;
1520                 }
1521             }
1522         }
1523         XFree( ret_prop );
1524     }
1525 
1526     return res;
1527 }
1528 
getRootPosition(int * x,int * y)1529 int AWindow::getRootPosition( int *x,
1530                               int *y )
1531 {
1532     Window child;
1533 
1534     if ( _created == false ) return 1;
1535 
1536     if ( XTranslateCoordinates( _aguix->getDisplay(),
1537                                 win,
1538                                 DefaultRootWindow( _aguix->getDisplay() ),
1539                                 0, 0,
1540                                 x, y,
1541                                 &child ) == True ) {
1542         return 0;
1543     }
1544 
1545     return 1;
1546 }
1547 
forceOpenPosition(int x,int y,bool max_h,bool max_v)1548 void AWindow::forceOpenPosition( int x, int y,
1549                                  bool max_h,
1550                                  bool max_v )
1551 {
1552     m_open_pos_x = x;
1553     m_open_pos_y = y;
1554     m_open_max_h = max_h;
1555     m_open_max_v = max_v;
1556     m_force_open_position = true;
1557 }
1558 
enableXDND()1559 void AWindow::enableXDND()
1560 {
1561     Atom version = 5;
1562 
1563     XChangeProperty( _aguix->getDisplay(),
1564                      win, _aguix->getAtom( AGUIX::XDNDAWARE ),
1565                      XA_ATOM, 32,
1566                      PropModeReplace, (unsigned char*)&version, 1 );
1567 
1568     m_enable_xdnd = true;
1569 }
1570 
acceptXDND()1571 bool AWindow::acceptXDND()
1572 {
1573     return m_enable_xdnd;
1574 }
1575 
findWindowForRootPos(int rx,int ry)1576 Window AWindow::findWindowForRootPos( int rx, int ry )
1577 {
1578     int x, y;
1579     Window child;
1580     Window previous_child = None;
1581     Window current_window = win;
1582 
1583     if ( XTranslateCoordinates( _aguix->getDisplay(),
1584                                 DefaultRootWindow( _aguix->getDisplay() ),
1585                                 current_window,
1586                                 rx, ry,
1587                                 &x, &y,
1588                                 &child ) != True ) {
1589         return None;
1590     }
1591 
1592     previous_child = child;
1593 
1594     while ( child != None ) {
1595         previous_child = child;
1596 
1597         if ( XTranslateCoordinates( _aguix->getDisplay(),
1598                                     current_window,
1599                                     child,
1600                                     x, y,
1601                                     &x, &y,
1602                                     &child ) != True ) {
1603             return None;
1604         }
1605 
1606         current_window = previous_child;
1607     }
1608 
1609     return previous_child;
1610 }
1611 
findWidgetForRootPos(int rx,int ry)1612 Widget *AWindow::findWidgetForRootPos( int rx, int ry )
1613 {
1614     Window child_win = findWindowForRootPos( rx, ry );
1615 
1616     if ( child_win == None ) return NULL;
1617 
1618     Widget *w = findWidgetForWindow( child_win );
1619 
1620     if ( AWindow *awin = dynamic_cast< AWindow * >( w ) ) {
1621         return awin->findWidgetForWindow( child_win );
1622     }
1623 
1624     return w;
1625 }
1626 
applyIcon()1627 void AWindow::applyIcon()
1628 {
1629     const unsigned long *data = NULL;
1630     size_t data_length = 0;
1631 
1632     if ( ! _aguix->getStandardIconData( &data, &data_length ) ) {
1633         return;
1634     }
1635 
1636     XChangeProperty( _aguix->getDisplay(),
1637                      win,
1638                      _aguix->getAtom( AGUIX::NET_WM_ICON_ATOM ),
1639                      _aguix->getAtom( AGUIX::CARDINAL_ATOM ),
1640                      32, PropModeReplace, (const unsigned char*)data, data_length );
1641 }
1642