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