1 /*
2  *  This file is part of the XForms library package.
3  *
4  *  XForms is free software; you can redistribute it and/or modify it
5  *  under the terms of the GNU Lesser General Public License as
6  *  published by the Free Software Foundation; either version 2.1, or
7  *  (at your option) any later version.
8  *
9  *  XForms is distributed in the hope that it will be useful, but
10  *  WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with XForms.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 /**
20  * \file win.c
21  *
22  *  This file is part of the XForms library package.
23  *  Copyright (c) 1996-2002  T.C. Zhao
24  *  All rights reserved.
25  *
26  * To isolate dependencies of XForms on the window system, we provide
27  * some system-neutual windowing services. It is expected that all
28  * XForms internal windowing will be done using these.
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <ctype.h>
36 #include "include/forms.h"
37 #include "flinternal.h"
38 #include "private/flvasprintf.h"
39 
40 
41 /*********************************************************************
42  *
43  * Windowing support.
44  * Geometry preference, opening/closing windows and geometry queries
45  *
46  * winclose is in appwin.c
47  *
48  ****************************************************************{****/
49 
50 static XSetWindowAttributes st_xswa;
51 static XSizeHints           st_xsh;
52 static XWMHints             st_xwmh;
53 static unsigned int         st_wmask;
54 static int                  st_wmborder;
55 static unsigned int         bwidth = 0;
56 
57 static int fli_winreparentxy( Window win,
58                               Window new_parent,
59                               int    x,
60                               int    y );
61 
62 extern FLI_WM_STUFF fli_wmstuff;       /* defined in flresource.c */
63 
64 
65 /*********************************************************************
66  * Default window attributes. Subject to pref_winsize and its friends
67  **********************************************************************/
68 
69 void
fli_default_xswa(void)70 fli_default_xswa( void )
71 {
72     /* OwnerGrab is needed for pop-up to work correctly */
73 
74     st_xswa.event_mask =   ExposureMask
75                          | KeyPressMask
76                          | KeyReleaseMask
77                          | ButtonPressMask
78                          | ButtonReleaseMask
79                          | OwnerGrabButtonMask
80                          | EnterWindowMask
81                          | LeaveWindowMask
82                          | ButtonMotionMask
83                          | PointerMotionMask
84                          | PointerMotionHintMask
85 /*
86                          | VisibilityChangeMask
87                          | PropertyChangeMask
88 */
89                          | StructureNotifyMask;
90 
91     /* Add event mask flags required by the input method/context */
92 
93     if( fli_context->xic )
94     {
95         long int fevents;
96 
97         if ( ! XGetICValues( fli_context->xic, XNFilterEvents,
98                              &fevents, NULL ) )
99             st_xswa.event_mask |= fevents;
100     }
101 
102     st_xswa.backing_store = fli_cntl.backingStore;
103     st_wmask = CWEventMask | CWBackingStore;
104 
105     /* Border_pixel must be set for 24bit TrueColor displays */
106 
107     st_xswa.border_pixel  = 0;
108     st_wmask             |= CWBorderPixel;
109     st_xsh.flags          = 0;
110 
111     /* Default size */
112 
113     st_xsh.width = st_xsh.base_width   = 320;
114     st_xsh.height = st_xsh.base_height = 200;
115 
116     /* Border */
117 
118     st_wmborder = FL_FULLBORDER;
119 
120     /* Keyboard focus. Need window manager's help  */
121 
122     st_xwmh.input         = True;
123     st_xwmh.initial_state = NormalState;
124     st_xwmh.flags         = InputHint | StateHint;
125 }
126 
127 
128 /************** Window sizes ******************{**/
129 
130 /***************************************
131  *  Open window with this size
132  ***************************************/
133 
134 void
fl_initial_winsize(FL_Coord w,FL_Coord h)135 fl_initial_winsize( FL_Coord w,
136                     FL_Coord h )
137 {
138     st_xsh.width   = st_xsh.base_width = w;
139     st_xsh.height  = st_xsh.base_height = h;
140     st_xsh.flags  |= USSize;
141 }
142 
143 
144 /***************************************
145  ***************************************/
146 
147 void
fl_initial_winstate(int state)148 fl_initial_winstate( int state )
149 {
150     st_xwmh.initial_state  = state;
151     st_xwmh.flags         |= StateHint;
152 }
153 
154 
155 /***************************************
156  ***************************************/
157 
158 void
fl_winicon(Window win,Pixmap p,Pixmap m)159 fl_winicon( Window win,
160             Pixmap p,
161             Pixmap m )
162 {
163     XWMHints lxwmh,
164              *xwmh;
165 
166     lxwmh.flags        = 0;
167     xwmh               = win ? &lxwmh : &st_xwmh;
168     xwmh->icon_pixmap  = p;
169     xwmh->icon_mask    = m;
170     xwmh->flags       |= IconPixmapHint | IconMaskHint;
171     if ( win )
172         XSetWMHints( flx->display, win, xwmh );
173 }
174 
175 
176 /***************************************
177  * Open window with this size and KEEP it this size if window manager
178  * coorporates
179  ***************************************/
180 
181 void
fl_winsize(FL_Coord w,FL_Coord h)182 fl_winsize( FL_Coord w,
183             FL_Coord h )
184 {
185     fl_initial_winsize( w, h );
186 
187     /* Try to disable interactive resizing */
188 
189     st_xsh.min_width   = st_xsh.max_width  = w;
190     st_xsh.min_height  = st_xsh.max_height = h;
191     st_xsh.flags      |= PMinSize | PMaxSize;
192 }
193 
194 
195 /***************************************
196  * Set a limit to the minimum size a window can take. Can be used
197  * while a window is visible. If window is not given, we take the
198  * request to mean a constraint for future windows.
199  ***************************************/
200 
201 void
fl_winminsize(Window win,FL_Coord w,FL_Coord h)202 fl_winminsize( Window   win,
203                FL_Coord w,
204                FL_Coord h )
205 {
206     XSizeHints mxsh,
207                *sh;
208 
209     /* Copy current constraints */
210 
211     mxsh            = st_xsh;
212     mxsh.flags      = 0;
213     sh              = win ? &mxsh : &st_xsh;
214 
215     sh->min_width   = w;
216     sh->min_height  = h;
217     sh->flags      |= PMinSize;
218     if ( win )
219         XSetWMNormalHints( flx->display, win, sh );
220 }
221 
222 
223 /***************************************
224  ***************************************/
225 
226 void
fl_winmaxsize(Window win,FL_Coord w,FL_Coord h)227 fl_winmaxsize( Window   win,
228                FL_Coord w,
229                FL_Coord h )
230 {
231     XSizeHints mxsh,
232                *sh;
233 
234     mxsh            = st_xsh;
235     mxsh.flags      = 0;
236     sh              = win ? &mxsh : &st_xsh;
237 
238     sh->max_width   = w;
239     sh->max_height  = h;
240     sh->flags      |= PMaxSize;
241     if ( win )
242         XSetWMNormalHints( flx->display, win, sh );
243 }
244 
245 
246 /***************************************
247  ***************************************/
248 
249 void
fl_winstepsize(Window win,FL_Coord dx,FL_Coord dy)250 fl_winstepsize( Window   win,
251                 FL_Coord dx,
252                 FL_Coord dy )
253 {
254     XSizeHints mxsh,
255                *sh;
256 
257     /* Copy current constraints */
258 
259     mxsh            = st_xsh;
260     mxsh.flags      = 0;
261     sh              = win ? &mxsh : &st_xsh;
262 
263     sh->width_inc   = dx;
264     sh->height_inc  = dy;
265     sh->flags      |= PResizeInc;
266     if ( win )
267         XSetWMNormalHints( flx->display, win, sh );
268 }
269 
270 
271 /******* End of basic win size routines **********}***/
272 
273 
274 /******* Window position routines **************{***/
275 
276 
277 /***************************************
278  ***************************************/
279 
280 void
fl_winposition(FL_Coord x,FL_Coord y)281 fl_winposition( FL_Coord x,
282                 FL_Coord y )
283 {
284     st_xsh.x = x;
285     st_xsh.y = y;
286     st_xsh.flags |= fli_wmstuff.pos_request;
287 }
288 
289 
290 /****** End of window positioning routines ******}*/
291 
292 
293 /***** Window position and size **************{****/
294 
295 
296 /***************************************
297  ***************************************/
298 
299 void
fl_initial_wingeometry(FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h)300 fl_initial_wingeometry( FL_Coord x,
301                         FL_Coord y,
302                         FL_Coord w,
303                         FL_Coord h )
304 {
305     fl_winposition( x, y );
306     fl_initial_winsize( w, h );
307 }
308 
309 
310 /***************************************
311  ***************************************/
312 
313 void
fl_wingeometry(FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h)314 fl_wingeometry( FL_Coord x,
315                 FL_Coord y,
316                 FL_Coord w,
317                 FL_Coord h )
318 {
319     fl_winposition( x, y );
320     fl_winsize( w, h );
321 }
322 
323 /***** End of geometry preference routine *******}**/
324 
325 /***** Misc. windowing routines *****************{*/
326 
327 
328 /***************************************
329  * Try to fix the aspect ration
330  ***************************************/
331 
332 void
fl_winaspect(Window win,FL_Coord x,FL_Coord y)333 fl_winaspect( Window   win,
334               FL_Coord x,
335               FL_Coord y )
336 {
337     XSizeHints lxsh,
338                *xsh;
339 
340     if ( x <= 0 || y <= 0 )
341     {
342         M_err( "fl_winaspect", "Bad aspect ratio" );
343         return;
344     }
345 
346     lxsh.flags         = 0;
347     xsh                = win ? &lxsh : &st_xsh;
348 
349     xsh->flags        |= PAspect;
350     xsh->min_aspect.x  = x;
351     xsh->min_aspect.y  = y;
352     xsh->max_aspect.x  = x;
353     xsh->max_aspect.y  = y;
354 
355     xsh->base_width    = xsh->width  = x;
356     xsh->base_height   = xsh->height = y;
357 
358     if ( xsh->base_width < 100 || xsh->base_height < 100 )
359     {
360         double fact = 100 / FL_max( x, y );
361 
362         xsh->base_width  *= fact;
363         xsh->base_height *= fact;
364     }
365 
366     if ( win )
367         XSetWMNormalHints( flx->display, win, xsh );
368 }
369 
370 
371 /***************************************
372  ***************************************/
373 
374 void
fl_noborder(void)375 fl_noborder( void )
376 {
377     st_wmborder = FL_NOBORDER;
378 }
379 
380 
381 /***************************************
382  ***************************************/
383 
384 void
fl_transient(void)385 fl_transient( void )
386 {
387     st_wmborder = FL_TRANSIENT;
388 }
389 
390 
391 /***************************************
392  ***************************************/
393 
394 void
fl_winmove(Window win,FL_Coord dx,FL_Coord dy)395 fl_winmove( Window   win,
396             FL_Coord dx,
397             FL_Coord dy)
398 {
399     if ( win )
400         XMoveWindow( flx->display, win, dx, dy );
401     else
402         fl_winposition( dx, dy );
403 }
404 
405 
406 /***************************************
407  ***************************************/
408 
409 void
fl_winreshape(Window win,FL_Coord dx,FL_Coord dy,FL_Coord w,FL_Coord h)410 fl_winreshape( Window   win,
411                FL_Coord dx,
412                FL_Coord dy,
413                FL_Coord w,
414                FL_Coord h )
415 {
416     if ( win )
417         XMoveResizeWindow( flx->display, win, dx, dy, w, h );
418     else
419     {
420         fl_winresize( win, w, h );
421         fl_winmove( win, dx, dy );
422     }
423 }
424 
425 
426 /***** End of misc. windowing routines **********}*/
427 
428 /********* Window geometry query routines ********{*/
429 
430 
431 /***************************************
432  ***************************************/
433 
434 void
fl_get_winsize(Window win,FL_Coord * w,FL_Coord * h)435 fl_get_winsize( Window     win,
436                 FL_Coord * w,
437                 FL_Coord * h )
438 {
439     unsigned int ww,
440                  hh,
441                  bjunk,
442                  djunk;
443     int xx,
444         yy;
445     Window root;
446 
447     XGetGeometry( flx->display, win, &root, &xx, &yy, &ww, &hh,
448                   &bjunk, &djunk );
449     *w = ww;
450     *h = hh;
451 }
452 
453 
454 /***************************************
455  ***************************************/
456 
457 void
fl_get_winorigin(Window win,FL_Coord * x,FL_Coord * y)458 fl_get_winorigin( Window     win,
459                   FL_Coord * x,
460                   FL_Coord * y )
461 {
462     int xx,
463         yy;
464     unsigned int ww,
465                  hh,
466                  bw,
467                  d;
468     Window root;
469 
470     XGetGeometry( flx->display, win, &root, &xx, &yy, &ww, &hh, &bw, &d );
471     XTranslateCoordinates( flx->display, win, root,
472                            - ( int ) bw, - ( int ) bw, &xx, &yy, &root );
473     *x = xx;
474     *y = yy;
475 }
476 
477 
478 /***************************************
479  ***************************************/
480 
481 void
fl_get_wingeometry(Window win,FL_Coord * x,FL_Coord * y,FL_Coord * w,FL_Coord * h)482 fl_get_wingeometry( Window     win,
483                     FL_Coord * x,
484                     FL_Coord * y,
485                     FL_Coord * w,
486                     FL_Coord * h )
487 {
488     int xx,
489         yy;
490     unsigned int ww,
491                  hh,
492                  bw,
493                  d;
494     Window root;
495 
496     XGetGeometry( flx->display, win, &root, &xx, &yy, &ww, &hh, &bw, &d );
497     XTranslateCoordinates( flx->display, win, root,
498                            - ( int ) bw, - ( int ) bw, &xx, &yy, &root );
499     *x = xx;
500     *y = yy;
501     *w = ww;
502     *h = hh;
503 }
504 
505 
506 /***** End of window geometry query routines ********}*/
507 
508 /******* Open window etc ***********************/
509 
510 
511 /***************************************
512  * If one of the forms is destoryed we want to know about it
513  * All window notices the Close window manager command
514  ***************************************/
515 
516 static void
setup_catch_destroy(Window win)517 setup_catch_destroy( Window win )
518 {
519     static Atom atom_delete_win;
520     static Atom atom_protocols;
521 
522     if ( ! atom_delete_win )
523         atom_delete_win = XInternAtom( flx->display, "WM_DELETE_WINDOW", 0 );
524 
525     if ( ! atom_protocols )
526         atom_protocols = XInternAtom( flx->display, "WM_PROTOCOLS", 0 );
527 
528     XChangeProperty( flx->display, win, atom_protocols, XA_ATOM, 32,
529                      PropModeReplace, ( unsigned char * ) &atom_delete_win, 1 );
530 }
531 
532 
533 /***************************************
534  * Waits until we know for sure the newly mapped window is visible
535  ***************************************/
536 
537 static void
wait_mapwin(Window win)538 wait_mapwin( Window win )
539 {
540     XEvent xev;
541 
542     if ( ! ( st_xswa.event_mask & StructureNotifyMask ) )
543     {
544         M_err( "wait_mapwin", "XForms improperly initialized" );
545         exit( 1 );
546     }
547 
548     /* Wait for the window to become mapped */
549 
550     do
551     {
552         XWindowEvent( flx->display, win, StructureNotifyMask, &xev );
553         fli_xevent_name( "waiting", &xev );
554     } while ( xev.type != MapNotify );
555 }
556 
557 
558 /***************************************
559  ***************************************/
560 
561 static char *
fl_label_to_res_name(const char * label)562 fl_label_to_res_name( const char * label )
563 {
564     static char res[ 54 ];
565 
566     fli_sstrcpy( res, label ? label : "", sizeof res );
567     fli_nuke_all_non_alnum( res );
568     if ( res[ 0 ] && isupper( ( unsigned char ) res[ 0 ] ) )
569         res[ 0 ] = tolower( ( unsigned char ) res[ 0 ] );
570     return res;
571 }
572 
573 
574 /***************************************
575  ***************************************/
576 
577 static char *
get_machine_name(Display * d)578 get_machine_name( Display * d )
579 {
580     static char machine_name[ 256 ] = "";
581     char *p;
582 
583     if ( machine_name[ 0 ] )
584         return machine_name;
585 
586     if ( gethostname( machine_name, sizeof machine_name - 1 ) )
587     {
588         M_err( "get_machine_name", "Unable to get host name" );
589         strcpy( machine_name, DisplayString( d ) );
590         if ( ( p = strchr( machine_name, ':' ) ) )
591             *p = '\0';
592     }
593 
594     return machine_name;
595 }
596 
597 
598 /***************************************
599  ***************************************/
600 
601 void
fli_set_winproperty(Window win,unsigned int prop)602 fli_set_winproperty( Window       win,
603                      unsigned int prop )
604 {
605     char **argv;
606     int argc;
607 
608     if ( prop & FLI_COMMAND_PROP )
609     {
610         argv = fl_get_cmdline_args( &argc );
611         XSetCommand( flx->display, win, argv, argc );
612     }
613 }
614 
615 
616 /***************************************
617  ***************************************/
618 
619 Window
fli_create_window(Window parent,Colormap m,const char * wname)620 fli_create_window( Window       parent,
621                    Colormap     m,
622                    const char * wname )
623 {
624     Window win;
625     XClassHint clh;
626     char *tmp;
627     XTextProperty xtpwname,
628                   xtpmachine;
629     char *label = fl_strdup( wname ? wname : "" );
630     FL_FORM *mainform = fl_get_app_mainform( );
631 
632     st_xswa.colormap = m;
633     st_wmask |= CWColormap;
634 
635     /* No decoration means unmanagered windows */
636 
637     if (    st_wmborder == FL_NOBORDER
638          && ( st_xsh.flags & fli_wmstuff.pos_request)
639                                                     == fli_wmstuff.pos_request )
640     {
641         /* Turning this on will make the window truely unmananged, might have
642            problems with the input focus and colormaps */
643 
644         st_xswa.override_redirect = True;
645         st_wmask |= CWOverrideRedirect;
646     }
647 
648     /* MWM uses root window's cursor, don't want that */
649 
650     if ( ( st_wmask & CWCursor ) != CWCursor )
651     {
652         st_xswa.cursor = fli_get_cursor_byname( FL_DEFAULT_CURSOR );
653         st_wmask |= CWCursor;
654     }
655 
656     if ( st_wmborder != FL_FULLBORDER )
657     {
658         st_xswa.save_under = True;
659         st_wmask |= CWSaveUnder;
660 
661     /* For small transient windows, we don't need backing store */
662 
663         if ( st_xsh.width < 200 || st_xsh.height < 200 )
664             st_xswa.backing_store = NotUseful;
665     }
666 
667     if ( mainform && mainform->window )
668     {
669         st_xwmh.flags |= WindowGroupHint;
670         st_xwmh.window_group = mainform->window;
671     }
672 
673 #if FL_DEBUG >= ML_WARN
674     fli_dump_state_info( fl_vmode, "fli_create_window" );
675 #endif
676 
677     win = XCreateWindow( flx->display, parent,
678                          st_xsh.x, st_xsh.y, st_xsh.width, st_xsh.height,
679                          bwidth, fli_depth( fl_vmode ), InputOutput,
680                          fli_visual( fl_vmode ), st_wmask, &st_xswa );
681 
682     if ( fli_cntl.debug > 3 )
683     {
684         XFlush( flx->display );
685         fprintf( stderr, "****CreateWin OK**** sleeping 1 seconds\n" );
686         sleep( 1 );
687     }
688 
689     clh.res_name = fl_label_to_res_name( label );
690     clh.res_class = "XForm";
691 
692     /* Command property is set elsewhere */
693 
694     xtpwname.value = 0;
695     XStringListToTextProperty( label ? &label : 0, 1, &xtpwname );
696 
697     XSetWMProperties( flx->display, win, &xtpwname, &xtpwname,
698                       0, 0, &st_xsh, &st_xwmh, &clh );
699 
700     if ( xtpwname.value )
701         XFree( xtpwname.value );
702 
703     xtpmachine.value = 0;
704     tmp = get_machine_name( flx->display );
705 
706     if ( XStringListToTextProperty( &tmp, 1, &xtpmachine ) )
707         XSetWMClientMachine( flx->display, win, &xtpmachine );
708 
709     if ( xtpmachine.value )
710         XFree( xtpmachine.value );
711 
712     fli_create_gc( win );
713 
714     if ( st_wmborder == FL_TRANSIENT )
715     {
716         if ( mainform && mainform->window )
717             XSetTransientForHint( flx->display, win, mainform->window );
718         else
719             XSetTransientForHint( flx->display, win, fl_root );
720     }
721 
722     fl_free( label );
723 
724     return win;
725 }
726 
727 
728 /***************************************
729  ***************************************/
730 
731 Window
fli_cmap_winopen(Window parent,Colormap m,const char * label)732 fli_cmap_winopen( Window       parent,
733                  Colormap     m,
734                  const char * label )
735 {
736     Window win = fli_create_window( parent, m, label );
737     return fl_winshow( win );
738 }
739 
740 
741 /***************************************
742  ***************************************/
743 
744 Window
fl_wincreate(const char * label)745 fl_wincreate( const char * label )
746 {
747     return fli_create_window( fl_root, fli_map( fl_vmode ), label) ;
748 }
749 
750 
751 /***************************************
752  ***************************************/
753 
754 Window
fl_winopen(const char * label)755 fl_winopen( const char * label )
756 {
757     fli_init_colormap( fl_vmode );
758     return fli_cmap_winopen( fl_root, fli_map( fl_vmode ), label );
759 }
760 
761 
762 /***************************************
763  ***************************************/
764 
765 Window
fl_winshow(Window win)766 fl_winshow( Window win )
767 {
768     XMapRaised( flx->display, win );
769 
770     /* Wait until the newly mapped window shows up */
771 
772     if ( st_xwmh.initial_state == NormalState )
773         wait_mapwin( win );
774 
775     setup_catch_destroy( win );
776     fl_winset( win );
777 
778     /* Re-initialize window defaults  */
779 
780     fli_default_xswa( );
781     return win;
782 }
783 
784 
785 /***************************************
786  ***************************************/
787 
788 int
fli_winreparentxy(Window win,Window new_parent,int x,int y)789 fli_winreparentxy( Window win,
790                    Window new_parent,
791                    int    x,
792                    int    y )
793 {
794 
795     if ( ! win || ! new_parent )
796         return -1;
797     else
798         return XReparentWindow( flx->display, win, new_parent, x, y );
799 }
800 
801 
802 /***************************************
803  ***************************************/
804 
805 int
fl_winreparent(Window win,Window new_parent)806 fl_winreparent( Window win,
807                 Window new_parent )
808 {
809     return fli_winreparentxy( win, new_parent, 0, 0 );
810 }
811 
812 
813 /***************************************
814  ***************************************/
815 
816 void
fl_winhide(Window win)817 fl_winhide( Window win )
818 {
819     if ( win )
820         XUnmapWindow( flx->display, win );
821 }
822 
823 
824 /***************************************
825  ***************************************/
826 
827 void
fl_winbackground(Window win,unsigned long bk)828 fl_winbackground( Window         win,
829                   unsigned long  bk )
830 {
831     if ( win == 0 )
832     {
833         st_xswa.background_pixel = bk;
834         st_wmask |= CWBackPixel;
835     }
836     else
837     {
838         XSetWindowBackground( flx->display, win, bk );
839         XClearWindow( flx->display, win );
840     }
841 }
842 
843 
844 /***************************************
845  ***************************************/
846 
847 void
fl_winset(Window win)848 fl_winset( Window win )
849 {
850     flx->win = win;
851 }
852 
853 
854 /***************************************
855  ***************************************/
856 
857 Window
fl_winget(void)858 fl_winget( void )
859 {
860     return flx->win;
861 }
862 
863 
864 /***************************************
865  ***************************************/
866 
867 int
fl_iconify(Window win)868 fl_iconify( Window win )
869 {
870     return XIconifyWindow( flx->display, win, flx->screen );
871 }
872 
873 
874 /***************************************
875  * Inform window manager about window constraints: minsize, maxsize,
876  * aspect ratio
877  ***************************************/
878 
879 void
fl_reset_winconstraints(Window win)880 fl_reset_winconstraints( Window win )
881 {
882     if ( win )
883         XSetWMNormalHints( flx->display, win, &st_xsh );
884 }
885 
886 
887 /***************************************
888  ***************************************/
889 
890 void
fl_winresize(Window win,FL_Coord neww,FL_Coord newh)891 fl_winresize( Window   win,
892               FL_Coord neww,
893               FL_Coord newh )
894 {
895     XSizeHints lxsh;
896     long fields;
897     FL_Coord curwh, curww;
898 
899     if ( ! win )
900         return;
901 
902     /* If sizes are the same we don't have to do anything. Some window managers
903        are too dumb to optimize this. */
904 
905     fl_get_winsize( win, &curww, &curwh );
906     if ( curww == neww && curwh == newh )
907         return;
908 
909     lxsh.flags = 0;
910     fields = 0;
911 
912     if ( XGetWMNormalHints( flx->display, win, &lxsh, &fields ) )
913     {
914         lxsh.width   = lxsh.base_width  = neww;
915         lxsh.height  = lxsh.base_height = newh;
916         lxsh.flags  |= USSize;
917 
918         if ( lxsh.flags & PMinSize && lxsh.flags & PMaxSize )
919         {
920             if ( lxsh.min_width == lxsh.max_width )
921                 lxsh.min_width = lxsh.max_width = neww;
922             if ( lxsh.min_height == lxsh.max_height )
923                 lxsh.min_height = lxsh.max_height = newh;
924         }
925 
926         /* Reset any contraints */
927 
928         if ( lxsh.flags & PMinSize )
929         {
930             if ( lxsh.min_width > neww )
931                 lxsh.min_width = neww;
932             if ( lxsh.min_height > newh )
933                 lxsh.min_height = newh;
934         }
935 
936         if ( lxsh.flags & PMaxSize )
937         {
938             if ( lxsh.max_width < neww )
939                 lxsh.max_width = neww;
940             if ( lxsh.max_height < newh )
941                 lxsh.max_height = newh;
942         }
943 
944         XSetWMNormalHints( flx->display, win, &lxsh );
945     }
946 
947     XResizeWindow( flx->display, win, neww, newh );
948     XFlush( flx->display );
949 }
950 
951 
952 /***************************************
953  * Check if a given window is valid. At the moment only used by
954  * canvas. A dirty hack. *****TODO *****
955  * If the main event loop is correct, we don't need to do this stuff
956  ***************************************/
957 
958 static int badwin;
959 
960 static int
valid_win_handler(Display * dpy FL_UNUSED_ARG,XErrorEvent * xev)961 valid_win_handler( Display     * dpy  FL_UNUSED_ARG,
962                    XErrorEvent * xev )
963 {
964     if ( xev->error_code == BadWindow || xev->error_code == BadDrawable )
965         badwin = 1;
966 
967     return 0;
968 }
969 
970 
971 /***************************************
972  ***************************************/
973 
974 int
fl_winisvalid(Window win)975 fl_winisvalid( Window win )
976 {
977     int ( * old )( Display *, XErrorEvent * );
978     FL_Coord w,
979              h;
980 
981     badwin = 0;
982     old = XSetErrorHandler( valid_win_handler );
983     fl_get_winsize( win, &w, &h );
984     XSetErrorHandler( old );
985     return ! badwin;
986 }
987 
988 
989 /***************************************
990  ***************************************/
991 
992 void
fl_wintitle(Window win,const char * title)993 fl_wintitle( Window       win,
994              const char * title )
995 {
996     XTextProperty xtp;
997 
998     if ( ! win && ! title )
999         return;
1000 
1001     xtp.value = 0;
1002     XStringListToTextProperty( ( char ** ) &title, 1, &xtp );
1003     XSetWMName( flx->display, win, &xtp );
1004     XSetWMIconName( flx->display, win, &xtp );
1005     if ( xtp.value )
1006         XFree( xtp.value );
1007 }
1008 
1009 
1010 /***************************************
1011  ***************************************/
1012 
1013 void
fl_wintitle_f(Window win,const char * fmt,...)1014 fl_wintitle_f( Window       win,
1015                const char * fmt,
1016                ... )
1017 {
1018     char *buf;
1019 
1020     EXPAND_FORMAT_STRING( buf, fmt );
1021     fl_wintitle( win, buf );
1022     fl_free( buf );
1023 }
1024 
1025 
1026 /***************************************
1027  ***************************************/
1028 
1029 void
fl_winicontitle(Window win,const char * title)1030 fl_winicontitle( Window       win,
1031                  const char * title )
1032 {
1033     XTextProperty xtp;
1034 
1035     if ( ! win || ! title )
1036         return;
1037 
1038     xtp.value = 0;
1039     XStringListToTextProperty( ( char ** ) &title, 1, &xtp );
1040     XSetWMIconName( flx->display, win, &xtp );
1041     if ( xtp.value )
1042         XFree( xtp.value );
1043 }
1044 
1045 
1046 /***************************************
1047  ***************************************/
1048 
1049 void
fl_winicontitle_f(Window win,const char * fmt,...)1050 fl_winicontitle_f( Window       win,
1051                    const char * fmt,
1052                    ... )
1053 {
1054     char *buf;
1055 
1056     EXPAND_FORMAT_STRING( buf, fmt );
1057     fl_winicontitle( win, buf );
1058     fl_free( buf );
1059 }
1060 
1061 
1062 /***************************************
1063  * Grab keyboard focus
1064  ***************************************/
1065 
1066 void
fl_winfocus(Window win)1067 fl_winfocus( Window win )
1068 {
1069     XSetInputFocus( flx->display, win, RevertToParent, CurrentTime );
1070 
1071 #if 0
1072     if ( fli_context->xic )
1073        XSetICValues( fli_context->xic,
1074                      XNClientWindow, win, XNFocusWindow, win, 0 );
1075 #endif
1076 }
1077 
1078 /********* END of Windowing support ***}**/
1079 
1080 
1081 /*
1082  * Local variables:
1083  * tab-width: 4
1084  * indent-tabs-mode: nil
1085  * End:
1086  */
1087