1 /********************************************************************************
2 * *
3 * T o p W i n d o w O b j e c t *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1998,2005 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
21 *********************************************************************************
22 * $Id: FXTopWindow.cpp,v 1.149.2.5 2005/10/25 12:34:28 fox Exp $ *
23 ********************************************************************************/
24 #include "xincs.h"
25 #include "fxver.h"
26 #include "fxdefs.h"
27 #include "fxpriv.h"
28 #include "FXHash.h"
29 #include "FXThread.h"
30 #include "FXStream.h"
31 #include "FXString.h"
32 #include "FXSize.h"
33 #include "FXPoint.h"
34 #include "FXRectangle.h"
35 #include "FXRegistry.h"
36 #include "FXAccelTable.h"
37 #include "FXApp.h"
38 #include "FXDCWindow.h"
39 #include "FXCursor.h"
40 #include "FXIcon.h"
41 #include "FXTopWindow.h"
42 #include "FXMainWindow.h"
43 #include "FXToolBar.h"
44 #include "FXToolBarGrip.h"
45
46 /*
47 Notes:
48 - Handle zero width/height case similar to FXWindow.
49 - Pass Size Hints to Window Manager as per ICCCM.
50 - Add padding options, as this is convenient for FXDialogBox subclasses;
51 for FXTopWindow/FXMainWindow, padding should default to 0, for FXDialogBox,
52 default to something easthetically pleasing...
53 - Now observes LAYOUT_FIX_X and LAYOUT_FIX_Y hints.
54 - LAYOUT_FIX_WIDTH and LAYOUT_FIX_HEIGHT take precedence over PACK_UNIFORM_WIDTH and
55 PACK_UNIFORM_HEIGHT!
56 */
57
58 // Definitions for Motif-style WM Hints.
59 #ifndef WIN32
60 #define MWM_HINTS_FUNCTIONS (1L << 0) // Definitions for FXMotifHints.flags
61 #define MWM_HINTS_DECORATIONS (1L << 1)
62 #define MWM_HINTS_INPUT_MODE (1L << 2)
63 #define MWM_HINTS_ALL (MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS|MWM_HINTS_INPUT_MODE)
64
65 #define MWM_FUNC_ALL (1L << 0) // Definitions for FXMotifHints.functions
66 #define MWM_FUNC_RESIZE (1L << 1)
67 #define MWM_FUNC_MOVE (1L << 2)
68 #define MWM_FUNC_MINIMIZE (1L << 3)
69 #define MWM_FUNC_MAXIMIZE (1L << 4)
70 #define MWM_FUNC_CLOSE (1L << 5)
71
72 #define MWM_DECOR_ALL (1L << 0) // Definitions for FXMotifHints.decorations
73 #define MWM_DECOR_BORDER (1L << 1)
74 #define MWM_DECOR_RESIZEH (1L << 2)
75 #define MWM_DECOR_TITLE (1L << 3)
76 #define MWM_DECOR_MENU (1L << 4)
77 #define MWM_DECOR_MINIMIZE (1L << 5)
78 #define MWM_DECOR_MAXIMIZE (1L << 6)
79
80 #define MWM_INPUT_MODELESS 0 // Values for FXMotifHints.inputmode
81 #define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
82 #define MWM_INPUT_SYSTEM_MODAL 2
83 #define MWM_INPUT_FULL_APPLICATION_MODAL 3
84 #endif
85
86
87 // Side layout modes
88 #define LAYOUT_SIDE_MASK (LAYOUT_SIDE_LEFT|LAYOUT_SIDE_RIGHT|LAYOUT_SIDE_TOP|LAYOUT_SIDE_BOTTOM)
89
90 // Layout modes
91 #define LAYOUT_MASK (LAYOUT_SIDE_MASK|LAYOUT_RIGHT|LAYOUT_CENTER_X|LAYOUT_BOTTOM|LAYOUT_CENTER_Y|LAYOUT_FIX_X|LAYOUT_FIX_Y|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
92
93 #define DISPLAY(app) ((Display*)((app)->display))
94
95 using namespace FX;
96
97
98 /*******************************************************************************/
99
100 namespace FX {
101
102 // Map
103 FXDEFMAP(FXTopWindow) FXTopWindowMap[]={
104 FXMAPFUNC(SEL_CLOSE,0,FXTopWindow::onCmdClose),
105 FXMAPFUNC(SEL_FOCUS_UP,0,FXTopWindow::onFocusUp),
106 FXMAPFUNC(SEL_FOCUS_DOWN,0,FXTopWindow::onFocusDown),
107 FXMAPFUNC(SEL_FOCUS_LEFT,0,FXTopWindow::onFocusLeft),
108 FXMAPFUNC(SEL_FOCUS_RIGHT,0,FXTopWindow::onFocusRight),
109 FXMAPFUNC(SEL_CHORE,FXTopWindow::ID_CLOSE,FXTopWindow::onCmdClose),
110 FXMAPFUNC(SEL_SIGNAL,FXTopWindow::ID_CLOSE,FXTopWindow::onCmdClose),
111 FXMAPFUNC(SEL_TIMEOUT,FXTopWindow::ID_CLOSE,FXTopWindow::onCmdClose),
112 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_CLOSE,FXTopWindow::onCmdClose),
113 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_MAXIMIZE,FXTopWindow::onCmdMaximize),
114 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_MINIMIZE,FXTopWindow::onCmdMinimize),
115 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_RESTORE,FXTopWindow::onCmdRestore),
116 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_SETSTRINGVALUE,FXTopWindow::onCmdSetStringValue),
117 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_GETSTRINGVALUE,FXTopWindow::onCmdGetStringValue),
118 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_SETICONVALUE,FXTopWindow::onCmdSetIconValue),
119 FXMAPFUNC(SEL_COMMAND,FXTopWindow::ID_GETICONVALUE,FXTopWindow::onCmdGetIconValue),
120 };
121
122
123 // Object implementation
FXIMPLEMENT_ABSTRACT(FXTopWindow,FXShell,FXTopWindowMap,ARRAYNUMBER (FXTopWindowMap))124 FXIMPLEMENT_ABSTRACT(FXTopWindow,FXShell,FXTopWindowMap,ARRAYNUMBER(FXTopWindowMap))
125
126
127 // Create toplevel window object & add to toplevel window list
128 FXTopWindow::FXTopWindow(FXApp* ap,const FXString& name,FXIcon *ic,FXIcon *mi,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs):
129 FXShell(ap,opts,x,y,w,h){
130 title=name;
131 icon=ic;
132 miniIcon=mi;
133 accelTable=new FXAccelTable;
134 padtop=pt;
135 padbottom=pb;
136 padleft=pl;
137 padright=pr;
138 hspacing=hs;
139 vspacing=vs;
140 }
141
142
143 // Create toplevel window object & add to toplevel window list
FXTopWindow(FXWindow * ow,const FXString & name,FXIcon * ic,FXIcon * mi,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs)144 FXTopWindow::FXTopWindow(FXWindow* ow,const FXString& name,FXIcon *ic,FXIcon *mi,FXuint opts,FXint x,FXint y,FXint w,FXint h,FXint pl,FXint pr,FXint pt,FXint pb,FXint hs,FXint vs):
145 FXShell(ow,opts,x,y,w,h){
146 title=name;
147 icon=ic;
148 miniIcon=mi;
149 accelTable=new FXAccelTable;
150 padtop=pt;
151 padbottom=pb;
152 padleft=pl;
153 padright=pr;
154 hspacing=hs;
155 vspacing=vs;
156 }
157
158
159 #ifdef WIN32
GetClass() const160 const char* FXTopWindow::GetClass() const { return "FXTopWindow"; }
161 #endif
162
163
164 // Create window
create()165 void FXTopWindow::create(){
166 FXShell::create();
167
168 // Create icons
169 if(icon) icon->create();
170 if(miniIcon) miniIcon->create();
171
172 if(xid){
173 if(getApp()->isInitialized()){
174
175 #ifndef WIN32
176 // Catch delete window
177 Atom protocols[2];
178 protocols[0]=getApp()->wmDeleteWindow;
179 protocols[1]=getApp()->wmTakeFocus;
180 XSetWMProtocols(DISPLAY(getApp()),xid,protocols,2);
181
182 // Set position for Window Manager
183 XSizeHints size;
184
185 size.flags=USSize|PSize|PWinGravity; // Let Window Manager place it
186 size.x=0;
187 size.y=0;
188 //if(xpos!=0 || ypos!=0){ // Force explicit position
189 size.flags|=USPosition|PPosition;
190 // }
191 size.x=xpos;
192 size.y=ypos;
193 size.min_width=0;
194 size.min_height=0;
195 size.base_width=0;
196 size.base_height=0;
197 if(!(options&DECOR_SHRINKABLE)){ // Can not shrink, so set min size
198 size.flags|=PMinSize|PBaseSize;
199 size.min_width=getDefaultWidth();
200 size.min_height=getDefaultHeight();
201 size.base_width=width;
202 size.base_height=height;
203 }
204 size.max_width=0;
205 size.max_height=0;
206 if(!(options&DECOR_STRETCHABLE)){ // Can not grow, so set max size
207 size.flags|=PMaxSize;
208 size.max_width=getDefaultWidth();
209 size.max_height=getDefaultHeight();
210 }
211 size.width=width;
212 size.height=height;
213 size.width_inc=0;
214 size.height_inc=0;
215 size.min_aspect.x=0;
216 size.min_aspect.y=0;
217 size.max_aspect.x=0;
218 size.max_aspect.y=0;
219 size.win_gravity=NorthWestGravity; // Tim Alexeevsky <realtim@mail.ru>
220 size.win_gravity=StaticGravity; // Account for border (ICCCM)
221
222 // Set hints
223 XSetWMNormalHints(DISPLAY(getApp()),xid,&size);
224
225 #endif
226
227 // Set title
228 settitle();
229
230 // Set decorations
231 setdecorations();
232
233 // Set icon for X-Windows
234 seticons();
235
236 // Tweak needed because the options affect window size
237 #ifdef WIN32
238 RECT rect;
239 SetRect(&rect,xpos,ypos,xpos+width,ypos+height);
240 DWORD dwStyle=GetWindowLong((HWND)xid,GWL_STYLE);
241 DWORD dwExStyle=GetWindowLong((HWND)xid,GWL_EXSTYLE);
242 AdjustWindowRectEx(&rect,dwStyle,FALSE,dwExStyle);
243 SetWindowPos((HWND)xid,NULL,rect.left,rect.top,FXMAX(rect.right-rect.left,1),FXMAX(rect.bottom-rect.top,1),SWP_NOZORDER|SWP_NOOWNERZORDER);
244 #endif
245 }
246 }
247 }
248
249
250 // Detach window
detach()251 void FXTopWindow::detach(){
252 FXShell::detach();
253 if(icon) icon->detach();
254 if(miniIcon) miniIcon->detach();
255 }
256
257
258 // Focus to this toplevel window
setFocus()259 void FXTopWindow::setFocus(){
260 FXShell::setFocus();
261 if(xid){
262 #ifndef WIN32
263 XSetInputFocus(DISPLAY(getApp()),xid,RevertToPointerRoot,CurrentTime);
264 #else
265 SetActiveWindow((HWND)xid);
266 //SetFocus((HWND)xid);
267 #endif
268 }
269 }
270
271
272 // Focus away from this toplevel window
killFocus()273 void FXTopWindow::killFocus(){
274 FXShell::killFocus();
275 if(xid){
276 #ifndef WIN32
277 Window win;
278 int dum;
279 XGetInputFocus(DISPLAY(getApp()),&win,&dum);
280 if(win==xid){
281 if(getOwner() && getOwner()->id()){
282 FXTRACE((100,"focus back to owner\n"));
283 XSetInputFocus(DISPLAY(getApp()),getOwner()->id(),RevertToPointerRoot,CurrentTime);
284 }
285 else{
286 FXTRACE((100,"focus back to NULL\n"));
287 XSetInputFocus(DISPLAY(getApp()),PointerRoot,RevertToPointerRoot,CurrentTime);
288 }
289 }
290 #else
291 /*
292 if(GetFocus()==(HWND)xid){
293 if(getOwner() && getOwner()->id()){
294 FXTRACE((100,"focus back to owner\n"));
295 SetFocus((HWND)getOwner()->id());
296 }
297 else{
298 FXTRACE((100,"focus back to NULL\n"));
299 SetFocus((HWND)NULL);
300 }
301 }
302 */
303 if(GetActiveWindow()==(HWND)xid){
304 if(getOwner() && getOwner()->id()){
305 FXTRACE((100,"focus back to owner\n"));
306 SetActiveWindow((HWND)getOwner()->id());
307 }
308 }
309 #endif
310 }
311 }
312
313
314 // Show and raise window
show()315 void FXTopWindow::show(){
316 FXShell::show();
317 raise();
318 }
319
320
321
322 // Show and raise window, placed properly on the screen
show(FXuint placement)323 void FXTopWindow::show(FXuint placement){
324 place(placement);
325 FXShell::show();
326 raise();
327 }
328
329
330
331 // Hide window
hide()332 void FXTopWindow::hide(){
333 if(flags&FLAG_SHOWN){
334 killFocus();
335 flags&=~FLAG_SHOWN;
336 if(xid){
337 #ifndef WIN32
338 XWithdrawWindow(DISPLAY(getApp()),xid,DefaultScreen(DISPLAY(getApp())));
339 #else
340 ShowWindow((HWND)xid,SW_HIDE);
341 #endif
342 }
343 }
344 }
345
346
347 // Raise and make foreground window
raise()348 void FXTopWindow::raise(){
349 FXShell::raise();
350 if(xid){
351 #ifdef WIN32
352 SetForegroundWindow((HWND)xid);
353 #endif
354 }
355 }
356
357
358 // Position the window based on placement
place(FXuint placement)359 void FXTopWindow::place(FXuint placement){
360 FXint rx,ry,rw,rh,ox,oy,ow,oh,wx,wy,ww,wh,x,y;
361 FXuint state;
362 FXWindow *over;
363
364 // Default placement:- leave it where it was
365 wx=getX();
366 wy=getY();
367 ww=getWidth();
368 wh=getHeight();
369
370 // Get root window size
371 #ifndef WIN32
372 rx=getRoot()->getX();
373 ry=getRoot()->getY();
374 rw=getRoot()->getWidth();
375 rh=getRoot()->getHeight();
376 #else
377 RECT rect;
378 //OSVERSIONINFO vinfo;
379 //memset(&vinfo,0,sizeof(vinfo));
380 //vinfo.dwOSVersionInfoSize=sizeof(vinfo);
381 //GetVersionEx(&vinfo);
382 #if (WINVER >= 0x500) || ((defined _WIN32_WINDOWS) && (_WIN32_WINDOWS >= 0x410))
383 HINSTANCE user32;
384 typedef BOOL (WINAPI* PFN_GETMONITORINFOA)(HMONITOR, LPMONITORINFO);
385 typedef HMONITOR (WINAPI* PFN_MONITORFROMRECTA)(LPRECT, DWORD);
386 PFN_GETMONITORINFOA GetMonitorInfoA;
387 PFN_MONITORFROMRECTA MonitorFromRectA;
388
389 // Suggested by "Daniel Gehriger" <gehriger@linkcad.com>
390 // The API does not exist on older Windows NT and 95, so
391 // We can't even link it, let alone call it.
392 // The solution is to ask the DLL if the function exists.
393 // And another patch from Lothar Scholtz; now it works!
394 if((user32=LoadLibrary("User32")) && (GetMonitorInfoA=reinterpret_cast<PFN_GETMONITORINFOA>(GetProcAddress(user32,"GetMonitorInfoA"))) && (MonitorFromRectA=reinterpret_cast<PFN_MONITORFROMRECTA>(GetProcAddress(user32,"MonitorFromRect")))){
395 MONITORINFOEX minfo;
396 HMONITOR hMon;
397 if(placement == PLACEMENT_CURSOR){
398 // Use mouse position to select screen.
399 getRoot()->getCursorPosition(x,y,state);
400 rect.left=x;
401 rect.right=x+1;
402 rect.top=y;
403 rect.bottom=y+1;
404 }
405 else{
406 // Use owner to select screen.
407 over=getOwner()?getOwner():getRoot();
408 over->translateCoordinatesTo(ox,oy,getRoot(),0,0);
409 ow=over->getWidth();
410 oh=over->getHeight();
411 rect.left=ox;
412 rect.right=ox+ow;
413 rect.top=oy;
414 rect.bottom=oy+oh;
415 }
416 hMon=MonitorFromRectA(&rect,MONITOR_DEFAULTTOPRIMARY);
417 memset(&minfo,0,sizeof(minfo));
418 minfo.cbSize=sizeof(minfo);
419 GetMonitorInfoA(hMon,&minfo);
420 rx=minfo.rcWork.left;
421 ry=minfo.rcWork.top;
422 rw=minfo.rcWork.right-minfo.rcWork.left;
423 rh=minfo.rcWork.bottom-minfo.rcWork.top;
424 }
425 else
426 #endif
427 {
428 // On Win95 and WinNT, we have to use the following
429 SystemParametersInfo(SPI_GETWORKAREA,sizeof(RECT),&rect,0);
430 rx=rect.left;
431 ry=rect.top;
432 rw=rect.right-rect.left;
433 rh=rect.bottom-rect.top;
434 }
435 #endif
436
437 // Placement policy
438 switch(placement){
439
440 // Place such that it contains the cursor
441 case PLACEMENT_CURSOR:
442
443 // Get dialog location in root coordinates
444 translateCoordinatesTo(wx,wy,getRoot(),0,0);
445
446 // Where's the mouse?
447 getRoot()->getCursorPosition(x,y,state);
448
449 // Place such that mouse in the middle, placing it as
450 // close as possible in the center of the owner window.
451 // Don't move the window unless the mouse is not inside.
452 if(!shown() || x<wx || y<wy || wx+ww<=x || wy+wh<=y){
453
454 // Get the owner
455 over=getOwner()?getOwner():getRoot();
456
457 // Get owner window size
458 ow=over->getWidth();
459 oh=over->getHeight();
460
461 // Owner's coordinates to root coordinates
462 over->translateCoordinatesTo(ox,oy,getRoot(),0,0);
463
464 // Adjust position
465 wx=ox+(ow-ww)/2;
466 wy=oy+(oh-wh)/2;
467
468 // Move by the minimal amount
469 if(x<wx) wx=x-20; else if(wx+ww<=x) wx=x-ww+20;
470 if(y<wy) wy=y-20; else if(wy+wh<=y) wy=y-wh+20;
471 }
472
473 // Adjust so dialog is fully visible
474 if(wx<rx) wx=rx+10;
475 if(wy<ry) wy=ry+10;
476 if(wx+ww>rw) wx=rw-ww-10;
477 if(wy+wh>rh) wy=rh-wh-10;
478 break;
479
480 // Place centered over the owner
481 case PLACEMENT_OWNER:
482
483 // Get the owner
484 over=getOwner()?getOwner():getRoot();
485
486 // Get owner window size
487 ow=over->getWidth();
488 oh=over->getHeight();
489
490 // Owner's coordinates to root coordinates
491 over->translateCoordinatesTo(ox,oy,getRoot(),0,0);
492
493 // Adjust position
494 wx=ox+(ow-ww)/2;
495 wy=oy+(oh-wh)/2;
496
497 // Adjust so dialog is fully visible
498 if(wx<rx) wx=rx+10;
499 if(wy<ry) wy=ry+10;
500 if(wx+ww>rw) wx=rw-ww-10;
501 if(wy+wh>rh) wy=rh-wh-10;
502 break;
503
504 // Place centered on the screen
505 case PLACEMENT_SCREEN:
506
507 // Adjust position
508 wx=rx+(rw-ww)/2;
509 wy=ry+(rh-wh)/2;
510 break;
511
512 // Place to make it fully visible
513 case PLACEMENT_VISIBLE:
514
515 // Adjust so dialog is fully visible
516 if(wx<rx) wx=rx+10;
517 if(wy<ry) wy=ry+10;
518 if(wx+ww>rw) wx=rw-ww-10;
519 if(wy+wh>rh) wy=rh-wh-10;
520 break;
521
522 // Place maximized
523 case PLACEMENT_MAXIMIZED:
524 wx=rx;
525 wy=ry;
526 ww=rw; // Yes, I know:- we should substract the borders;
527 wh=rh; // trouble is, no way to know how big those are....
528 break;
529
530 // Default placement
531 case PLACEMENT_DEFAULT:
532 default:
533 break;
534 }
535
536 // Place it
537 position(wx,wy,ww,wh);
538 }
539
540
541 #ifdef WIN32
542
543
544 // Make HICON from FXIcon
makeicon(FXIcon * icon)545 void* FXTopWindow::makeicon(FXIcon* icon){
546 ICONINFO iconinfo;
547 iconinfo.fIcon=TRUE;
548 iconinfo.xHotspot=0;
549 iconinfo.yHotspot=0;
550 iconinfo.hbmMask=(HBITMAP)icon->shape;
551 iconinfo.hbmColor=(HBITMAP)icon->id();
552 return (void*)CreateIconIndirect(&iconinfo);
553 }
554
555
556 #endif
557
558
559
560 // Set large icon(s)
seticons()561 void FXTopWindow::seticons(){
562
563 // Set icon for X-Windows
564 #ifndef WIN32
565 FXWindow *own=this;
566 XWMHints wmhints;
567 wmhints.flags=InputHint|StateHint;
568 wmhints.input=TRUE; // True, but ICCCM says it should be FALSE....
569 wmhints.initial_state=NormalState;
570 if(icon){
571 if(!icon->xid || !icon->shape){ fxerror("%s::setIcon: illegal icon specified.\n",getClassName()); }
572 wmhints.flags|=IconPixmapHint|IconMaskHint;
573 wmhints.icon_pixmap=icon->xid;
574 wmhints.icon_mask=icon->shape;
575 }
576 else if(miniIcon){
577 if(!miniIcon->xid || !miniIcon->shape){ fxerror("%s::setMiniIcon: illegal icon specified.\n",getClassName()); }
578 wmhints.flags|=IconPixmapHint|IconMaskHint;
579 wmhints.icon_pixmap=miniIcon->xid;
580 wmhints.icon_mask=miniIcon->shape;
581 }
582 while(own->getOwner()){ // Find the ultimate owner of the whole chain
583 own=own->getOwner();
584 }
585 if(own && own->id()){ // Set the window_group id; all windows in the group should be iconified together
586 wmhints.flags|=WindowGroupHint;
587 wmhints.window_group=own->id();
588 }
589 XSetWMHints(DISPLAY(getApp()),xid,&wmhints);
590
591 // Set both large and mini icon for MS-Windows
592 #else
593 HICON icold,icnew;
594 icnew=NULL;
595 if(icon){
596 ICONINFO iconinfo;
597 iconinfo.fIcon=TRUE;
598 iconinfo.xHotspot=0;
599 iconinfo.yHotspot=0;
600 iconinfo.hbmMask=(HBITMAP)icon->shape;
601 iconinfo.hbmColor=(HBITMAP)icon->xid;
602 icnew=CreateIconIndirect(&iconinfo);
603 }
604 if((icold=(HICON)SendMessage((HWND)xid,WM_SETICON,ICON_BIG,(LPARAM)icnew))!=0){
605 DestroyIcon(icold);
606 }
607 icnew=NULL;
608 if(miniIcon){
609 ICONINFO iconinfo;
610 iconinfo.fIcon=TRUE;
611 iconinfo.xHotspot=0;
612 iconinfo.yHotspot=0;
613 iconinfo.hbmMask=(HBITMAP)miniIcon->shape;
614 iconinfo.hbmColor=(HBITMAP)miniIcon->xid;
615 icnew=CreateIconIndirect(&iconinfo);
616 }
617 if((icold=(HICON)SendMessage((HWND)xid,WM_SETICON,ICON_SMALL,(LPARAM)icnew))!=0){
618 DestroyIcon(icold);
619 }
620 #endif
621 }
622
623
624 // Set title
settitle()625 void FXTopWindow::settitle(){
626 if(!title.empty()){
627 #ifndef WIN32
628 XTextProperty t;
629 char *s;
630 s=(char*)title.text();
631 if(XStringListToTextProperty((char**)&s,1,&t)){
632 XSetWMIconName(DISPLAY(getApp()),xid,&t);
633 XSetWMName(DISPLAY(getApp()),xid,&t);
634 XFree(t.value);
635 }
636 #else
637 SetWindowText((HWND)xid,title.text());
638 #endif
639 }
640 }
641
642
643
644 // Set decorations
setdecorations()645 void FXTopWindow::setdecorations(){
646 #ifndef WIN32
647 struct {
648 long flags;
649 long functions;
650 long decorations;
651 long inputmode;
652 } prop;
653 prop.flags=MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS|MWM_HINTS_INPUT_MODE;
654 prop.decorations=0;
655 prop.functions=MWM_FUNC_MOVE;
656 prop.inputmode=MWM_INPUT_MODELESS;
657 if(options&DECOR_TITLE){
658 prop.decorations|=MWM_DECOR_TITLE;
659 }
660 if(options&DECOR_MINIMIZE){
661 prop.decorations|=MWM_DECOR_MINIMIZE;
662 prop.functions|=MWM_FUNC_MINIMIZE;
663 }
664 if(options&DECOR_MAXIMIZE){
665 prop.decorations|=MWM_DECOR_MAXIMIZE;
666 prop.functions|=MWM_FUNC_MAXIMIZE;
667 }
668 if(options&DECOR_CLOSE){
669 prop.functions|=MWM_FUNC_CLOSE;
670 }
671 if(options&DECOR_BORDER){
672 prop.decorations|=MWM_DECOR_BORDER;
673 }
674 if(options&(DECOR_SHRINKABLE|DECOR_STRETCHABLE)){
675 if(options&DECOR_BORDER) prop.decorations|=MWM_DECOR_RESIZEH; // Only grips if border
676 prop.functions|=MWM_FUNC_RESIZE;
677 }
678 if(options&DECOR_MENU){
679 prop.decorations|=MWM_DECOR_MENU;
680 prop.functions|=MWM_FUNC_RESIZE;
681 }
682 XChangeProperty(DISPLAY(getApp()),xid,getApp()->wmMotifHints,getApp()->wmMotifHints,32,PropModeReplace,(unsigned char*)&prop,4);
683 #else
684
685 // Get old style
686 DWORD dwStyle=GetWindowLong((HWND)xid,GWL_STYLE);
687 RECT rect;
688
689 // Moved here just in case the size changes behind our backs
690 SetRect(&rect,0,0,width,height);
691
692 // Change style setting; note, under Windows, if we want a minimize,
693 // maximize, or close button, we also need a window menu style as well.
694 // Also, if you want a title, you will need a border.
695 if(options&DECOR_BORDER) dwStyle|=WS_BORDER; else dwStyle&=~WS_BORDER;
696 if(options&DECOR_TITLE) dwStyle|=WS_CAPTION; else dwStyle&=~WS_DLGFRAME;
697 if(options&DECOR_RESIZE) dwStyle|=WS_THICKFRAME; else dwStyle&=~WS_THICKFRAME;
698 if(options&DECOR_MENU) dwStyle|=WS_SYSMENU; else dwStyle&=~WS_SYSMENU;
699 if(options&DECOR_CLOSE) dwStyle|=WS_SYSMENU;
700 if(options&DECOR_MINIMIZE) dwStyle|=(WS_MINIMIZEBOX|WS_SYSMENU); else dwStyle&=~WS_MINIMIZEBOX;
701 if(options&DECOR_MAXIMIZE) dwStyle|=(WS_MAXIMIZEBOX|WS_SYSMENU); else dwStyle&=~WS_MAXIMIZEBOX;
702
703 // Set new style
704 SetWindowLong((HWND)xid,GWL_STYLE,dwStyle);
705
706 // Patch from Stephane Ancelot <sancelot@wanadoo.fr> and Sander Jansen <sander@knology.net>
707 HMENU sysmenu=GetSystemMenu((HWND)xid,FALSE);
708 if(sysmenu){
709 if(options&DECOR_CLOSE)
710 EnableMenuItem(sysmenu,SC_CLOSE,MF_ENABLED);
711 else
712 EnableMenuItem(sysmenu,SC_CLOSE,MF_GRAYED);
713 }
714
715 // Moved here just in case SetWindowLong GWL_STYLE has changed
716 // the GWL_EXSTYLE behind the scenes...
717 DWORD dwExStyle=GetWindowLong((HWND)xid,GWL_EXSTYLE);
718
719 // Adjust non-client area size based on new style
720 AdjustWindowRectEx(&rect,dwStyle,FALSE,dwExStyle);
721 SetWindowPos((HWND)xid,NULL,0,0,FXMAX(rect.right-rect.left,1),FXMAX(rect.bottom-rect.top,1),SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER);
722 RedrawWindow((HWND)xid,NULL,NULL,RDW_FRAME|RDW_INVALIDATE);
723 #endif
724 }
725
726
727 // Obtain border sizes added to our window by the window manager
getWMBorders(FXint & left,FXint & right,FXint & top,FXint & bottom)728 FXbool FXTopWindow::getWMBorders(FXint& left,FXint& right,FXint& top,FXint& bottom){
729 left=right=top=bottom=0;
730 if(xid){
731 #ifdef WIN32
732 #if(WINVER >= 0x0500)
733 WINDOWINFO wi;
734 GetWindowInfo((HWND)xid,&wi);
735 left=wi.rcClient.left-wi.rcWindow.left;
736 top=wi.rcClient.top-wi.rcWindow.top;
737 right=wi.rcWindow.right-wi.rcClient.right;
738 bottom=wi.rcWindow.bottom-wi.rcClient.bottom;
739 #endif
740 #else
741 unsigned int sx,sy,msx,msy,cn,border,depth;
742 Window w,rw,pw,*cw;
743 int ox,oy;
744 w=xid;
745 XGetGeometry(DISPLAY(getApp()),w,&rw,&ox,&oy,&msx,&msy,&border,&depth);
746 do{
747 XQueryTree(DISPLAY(getApp()),w,&rw,&pw,&cw,&cn);
748 XFree(cw);
749 XGetGeometry(DISPLAY(getApp()),w,&rw,&ox,&oy,&sx,&sy,&border,&depth);
750 if(pw!=rw){
751 left+=ox;
752 top+=oy;
753 }
754 w=pw;
755 }
756 while(w!=rw);
757 right=(sx-msx-left);
758 bottom=(sy-msy-top);
759 #endif
760 return TRUE;
761 }
762 return FALSE;
763 }
764
765
766 // Change decorations
setDecorations(FXuint decorations)767 void FXTopWindow::setDecorations(FXuint decorations){
768 FXuint opts=(options&~DECOR_ALL) | (decorations&DECOR_ALL);
769 if(options!=opts){
770 options=opts;
771 if(xid) setdecorations();
772 recalc();
773 }
774 }
775
776
777 // Get decorations
getDecorations() const778 FXuint FXTopWindow::getDecorations() const {
779 return options&DECOR_ALL;
780 }
781
782
783 // Iconify window
maximize(FXbool notify)784 FXbool FXTopWindow::maximize(FXbool notify){
785 if(!isMaximized()){
786 if(xid){
787 #ifndef WIN32
788 XEvent se;
789
790 // Maximize
791 se.xclient.type=ClientMessage;
792 se.xclient.display=DISPLAY(getApp());
793 se.xclient.message_type=getApp()->wmNetState;
794 se.xclient.format=32;
795 se.xclient.window=xid;
796 se.xclient.data.l[0]=2; // 0=_NET_WM_STATE_REMOVE, 1=_NET_WM_STATE_ADD, 2=_NET_WM_STATE_TOGGLE
797 se.xclient.data.l[1]=getApp()->wmNetHMaximized;
798 se.xclient.data.l[2]=getApp()->wmNetVMaximized;
799 se.xclient.data.l[3]=0;
800 se.xclient.data.l[4]=0;
801 XSendEvent(DISPLAY(getApp()),XDefaultRootWindow(DISPLAY(getApp())),False,SubstructureRedirectMask|SubstructureNotifyMask,&se);
802
803 // Restore from minimized
804 XMapWindow(DISPLAY(getApp()),xid);
805 #else
806 ShowWindow((HWND)xid,SW_MAXIMIZE);
807 #endif
808 }
809 if(notify && target){target->tryHandle(this,FXSEL(SEL_MAXIMIZE,message),NULL);}
810 return TRUE;
811 }
812 return FALSE;
813 }
814
815
816 // Miminize or iconify window
minimize(FXbool notify)817 FXbool FXTopWindow::minimize(FXbool notify){
818 if(!isMinimized()){
819 if(xid){
820 #ifndef WIN32
821 XIconifyWindow(DISPLAY(getApp()),xid,DefaultScreen(DISPLAY(getApp())));
822 #else
823 ShowWindow((HWND)xid,SW_MINIMIZE);
824 #endif
825 }
826 if(notify && target){target->tryHandle(this,FXSEL(SEL_MINIMIZE,message),NULL);}
827 return TRUE;
828 }
829 return FALSE;
830 }
831
832
833 // Restore window
restore(FXbool notify)834 FXbool FXTopWindow::restore(FXbool notify){
835 if(isMinimized() || isMaximized()){
836 if(xid){
837 #ifndef WIN32
838 XEvent se;
839
840 // Restore from maximized
841 se.xclient.type=ClientMessage;
842 se.xclient.display=DISPLAY(getApp());
843 se.xclient.message_type=getApp()->wmNetState;
844 se.xclient.format=32;
845 se.xclient.window=xid;
846 se.xclient.data.l[0]=0; // 0=_NET_WM_STATE_REMOVE, 1=_NET_WM_STATE_ADD, 2=_NET_WM_STATE_TOGGLE
847 se.xclient.data.l[1]=getApp()->wmNetHMaximized;
848 se.xclient.data.l[2]=getApp()->wmNetVMaximized;
849 se.xclient.data.l[3]=0;
850 se.xclient.data.l[4]=0;
851 XSendEvent(DISPLAY(getApp()),XDefaultRootWindow(DISPLAY(getApp())),False,SubstructureRedirectMask|SubstructureNotifyMask,&se);
852
853 // Restore from minimized
854 XMapWindow(DISPLAY(getApp()),xid);
855 #else
856 ShowWindow((HWND)xid,SW_RESTORE);
857 #endif
858 }
859 if(notify && target){target->tryHandle(this,FXSEL(SEL_RESTORE,message),NULL);}
860 return TRUE;
861 }
862 return FALSE;
863 }
864
865
866 // Attempt to close the window, return TRUE if actually closed
close(FXbool notify)867 FXbool FXTopWindow::close(FXbool notify){
868 register FXWindow *window;
869
870 // Ask target if desired
871 if(!notify || !target || !target->tryHandle(this,FXSEL(SEL_CLOSE,message),NULL)){
872
873 // Target will receive no further messages from us
874 setTarget(NULL);
875 setSelector(0);
876
877 // If there was another main level window still visible, that's all we do
878 for(window=getRoot()->getFirst(); window; window=window->getNext()){
879 if(window!=this && window->isMemberOf(FXMETACLASS(FXMainWindow))){
880 goto x;
881 }
882 }
883
884 // We've just hidden the last remaining top level window:- quit the application
885 getApp()->handle(this,FXSEL(SEL_COMMAND,FXApp::ID_QUIT),NULL);
886
887 // Self destruct
888 x: delete this;
889
890 // Was closed
891 return TRUE;
892 }
893 return FALSE;
894 }
895
896
897 // Return TRUE if window has been maximized
isMaximized() const898 FXbool FXTopWindow::isMaximized() const {
899 FXbool maximized=FALSE;
900 if(xid){
901 #ifndef WIN32
902 unsigned long nitems,after,i;
903 FXID *netstate;
904 Atom actualtype;
905 int actualformat;
906
907 // For Window Managers supporting the Extended Window Manager Hints
908 // See http://www.freedesktop.org/ for the official documentation of EWMH
909 if(Success==XGetWindowProperty(DISPLAY(getApp()),xid,getApp()->wmNetState,0,2,FALSE,AnyPropertyType,&actualtype,&actualformat,&nitems,&after,(unsigned char**)&netstate)){
910 if(actualtype==XA_ATOM && actualformat==32){
911 FXTRACE((100,"got _NET_WM_STATE property\n"));
912 for(i=0; i<nitems; i++){
913 if(netstate[i]==getApp()->wmNetHMaximized) maximized=TRUE;
914 if(netstate[i]==getApp()->wmNetVMaximized) maximized=TRUE;
915 }
916 FXTRACE((100,"maximized=%d\n",maximized));
917 }
918 XFree((char*)netstate);
919 }
920 #else
921 maximized=IsZoomed((HWND)xid);
922 #endif
923 }
924 return maximized;
925 }
926
927
928 // Return TRUE if window has been minimized
isMinimized() const929 FXbool FXTopWindow::isMinimized() const {
930 FXbool minimized=FALSE;
931 if(xid){
932 #ifndef WIN32
933 unsigned long length,after;
934 unsigned char *prop;
935 Atom actualtype;
936 int actualformat;
937
938 // This is ICCCM compliant method to ask about WM_STATE
939 if(Success==XGetWindowProperty(DISPLAY(getApp()),xid,getApp()->wmState,0,2,FALSE,AnyPropertyType,&actualtype,&actualformat,&length,&after,&prop)){
940 if(actualformat==32){
941 minimized=(IconicState==*((FXuint*)prop));
942 }
943 XFree((char*)prop);
944 }
945 #else
946 minimized=IsIconic((HWND)xid);
947 #endif
948 }
949 return minimized;
950 }
951
952
953 // Request for toplevel window move
move(FXint x,FXint y)954 void FXTopWindow::move(FXint x,FXint y){
955 if((x!=xpos) || (y!=ypos)){
956 xpos=x;
957 ypos=y;
958 if(xid){
959 #ifndef WIN32
960 XWindowChanges cw;
961 cw.x=xpos;
962 cw.y=ypos;
963 XReconfigureWMWindow(DISPLAY(getApp()),xid,DefaultScreen(DISPLAY(getApp())),CWX|CWY,&cw);
964 #else
965 // Calculate the required window position based on the desired
966 // position of the *client* rectangle.
967 RECT rect;
968 SetRect(&rect,xpos,ypos,0,0);
969 DWORD dwStyle=GetWindowLong((HWND)xid,GWL_STYLE);
970 DWORD dwExStyle=GetWindowLong((HWND)xid,GWL_EXSTYLE);
971 AdjustWindowRectEx(&rect,dwStyle,FALSE,dwExStyle);
972 SetWindowPos((HWND)xid,NULL,rect.left,rect.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER);
973 #endif
974 }
975 }
976 }
977
978
979 // Request for toplevel window resize
resize(FXint w,FXint h)980 void FXTopWindow::resize(FXint w,FXint h){
981 if((flags&FLAG_DIRTY) || (w!=width) || (h!=height)){
982 width=FXMAX(w,1);
983 height=FXMAX(h,1);
984 if(xid){
985 #ifndef WIN32
986 XWindowChanges cw;
987 cw.width=width;
988 cw.height=height;
989 XReconfigureWMWindow(DISPLAY(getApp()),xid,DefaultScreen(DISPLAY(getApp())),CWWidth|CWHeight,&cw);
990 #else
991 // Calculate the required window size based on the desired
992 // size of the *client* rectangle.
993 RECT rect;
994 SetRect(&rect,0,0,width,height);
995 DWORD dwStyle=GetWindowLong((HWND)xid,GWL_STYLE);
996 DWORD dwExStyle=GetWindowLong((HWND)xid,GWL_EXSTYLE);
997 AdjustWindowRectEx(&rect,dwStyle,FALSE,dwExStyle);
998 SetWindowPos((HWND)xid,NULL,0,0,FXMAX(rect.right-rect.left,1),FXMAX(rect.bottom-rect.top,1),SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER);
999 #endif
1000 layout();
1001 }
1002 }
1003 }
1004
1005
1006 // Request for toplevel window reposition
position(FXint x,FXint y,FXint w,FXint h)1007 void FXTopWindow::position(FXint x,FXint y,FXint w,FXint h){
1008 if((flags&FLAG_DIRTY) || (x!=xpos) || (y!=ypos) || (w!=width) || (h!=height)){
1009 xpos=x;
1010 ypos=y;
1011 width=FXMAX(w,1);
1012 height=FXMAX(h,1);
1013 if(xid){
1014 #ifndef WIN32
1015 XWindowChanges cw;
1016 cw.x=xpos;
1017 cw.y=ypos;
1018 cw.width=width;
1019 cw.height=height;
1020 XReconfigureWMWindow(DISPLAY(getApp()),xid,DefaultScreen(DISPLAY(getApp())),CWX|CWY|CWWidth|CWHeight,&cw);
1021 #else
1022 // Calculate the required window position & size based on the desired
1023 // position & size of the *client* rectangle.
1024 RECT rect;
1025 SetRect(&rect,xpos,ypos,xpos+width,ypos+height);
1026 DWORD dwStyle=GetWindowLong((HWND)xid,GWL_STYLE);
1027 DWORD dwExStyle=GetWindowLong((HWND)xid,GWL_EXSTYLE);
1028 AdjustWindowRectEx(&rect,dwStyle,FALSE,dwExStyle);
1029 SetWindowPos((HWND)xid,NULL,rect.left,rect.top,FXMAX(rect.right-rect.left,1),FXMAX(rect.bottom-rect.top,1),SWP_NOZORDER|SWP_NOOWNERZORDER);
1030 #endif
1031 layout();
1032 }
1033 }
1034 }
1035
1036
1037 // Compute minimum width based on child layout hints
getDefaultWidth()1038 FXint FXTopWindow::getDefaultWidth(){
1039 register FXint w,wcum,wmax,mw=0;
1040 register FXWindow* child;
1041 register FXuint hints;
1042 wmax=wcum=0;
1043 if(options&PACK_UNIFORM_WIDTH) mw=maxChildWidth();
1044 for(child=getLast(); child; child=child->getPrev()){
1045 if(child->shown()){
1046 hints=child->getLayoutHints();
1047 if(hints&LAYOUT_FIX_WIDTH) w=child->getWidth();
1048 else if(options&PACK_UNIFORM_WIDTH) w=mw;
1049 else w=child->getDefaultWidth();
1050 if((hints&LAYOUT_RIGHT)&&(hints&LAYOUT_CENTER_X)){ // Fixed X
1051 w=child->getX()+w;
1052 if(w>wmax) wmax=w;
1053 }
1054 else if(hints&LAYOUT_SIDE_LEFT){ // Left or right
1055 if(child->getNext()) wcum+=hspacing;
1056 wcum+=w;
1057 }
1058 else{
1059 if(w>wcum) wcum=w;
1060 }
1061 }
1062 }
1063 return padleft+padright+FXMAX(wcum,wmax);
1064 }
1065
1066
1067 // Compute minimum height based on child layout hints
getDefaultHeight()1068 FXint FXTopWindow::getDefaultHeight(){
1069 register FXint h,hcum,hmax,mh=0;
1070 register FXWindow* child;
1071 register FXuint hints;
1072 hmax=hcum=0;
1073 if(options&PACK_UNIFORM_HEIGHT) mh=maxChildHeight();
1074 for(child=getLast(); child; child=child->getPrev()){
1075 if(child->shown()){
1076 hints=child->getLayoutHints();
1077 if(hints&LAYOUT_FIX_HEIGHT) h=child->getHeight();
1078 else if(options&PACK_UNIFORM_HEIGHT) h=mh;
1079 else h=child->getDefaultHeight();
1080 if((hints&LAYOUT_BOTTOM)&&(hints&LAYOUT_CENTER_Y)){ // Fixed Y
1081 h=child->getY()+h;
1082 if(h>hmax) hmax=h;
1083 }
1084 else if(!(hints&LAYOUT_SIDE_LEFT)){ // Top or bottom
1085 if(child->getNext()) hcum+=vspacing;
1086 hcum+=h;
1087 }
1088 else{
1089 if(h>hcum) hcum=h;
1090 }
1091 }
1092 }
1093 return padtop+padbottom+FXMAX(hcum,hmax);
1094 }
1095
1096
1097 // Recalculate layout
layout()1098 void FXTopWindow::layout(){
1099 register FXint left,right,top,bottom,x,y,w,h;
1100 register FXint mw=0,mh=0;
1101 register FXWindow* child;
1102 register FXuint hints;
1103
1104 // Placement rectangle; right/bottom non-inclusive
1105 left=padleft;
1106 right=width-padright;
1107 top=padtop;
1108 bottom=height-padbottom;
1109
1110 // Get maximum child size
1111 if(options&PACK_UNIFORM_WIDTH) mw=maxChildWidth();
1112 if(options&PACK_UNIFORM_HEIGHT) mh=maxChildHeight();
1113
1114 // Pack them in the cavity
1115 for(child=getFirst(); child; child=child->getNext()){
1116 if(child->shown()){
1117 hints=child->getLayoutHints();
1118 x=child->getX();
1119 y=child->getY();
1120
1121 // Vertical
1122 if(hints&LAYOUT_SIDE_LEFT){
1123
1124 // Height
1125 if(hints&LAYOUT_FIX_HEIGHT) h=child->getHeight();
1126 else if(options&PACK_UNIFORM_HEIGHT) h=mh;
1127 else if(hints&LAYOUT_FILL_Y) h=bottom-top;
1128 else h=child->getDefaultHeight();
1129
1130 // Width
1131 if(hints&LAYOUT_FIX_WIDTH) w=child->getWidth();
1132 else if(options&PACK_UNIFORM_WIDTH) w=mw;
1133 else if(hints&LAYOUT_FILL_X) w=right-left;
1134 else w=child->getWidthForHeight(h); // Width is a function of height!
1135
1136 // Y
1137 if(!((hints&LAYOUT_BOTTOM)&&(hints&LAYOUT_CENTER_Y))){
1138 if(hints&LAYOUT_CENTER_Y) y=top+(bottom-top-h)/2;
1139 else if(hints&LAYOUT_BOTTOM) y=bottom-h;
1140 else y=top;
1141 }
1142
1143 // X
1144 if(!((hints&LAYOUT_RIGHT)&&(hints&LAYOUT_CENTER_X))){
1145 if(hints&LAYOUT_CENTER_X) x=left+(right-left-w)/2;
1146 else if(hints&LAYOUT_SIDE_BOTTOM){ // Right
1147 x=right-w;
1148 right-=(w+hspacing);
1149 }
1150 else{ // Left
1151 x=left;
1152 left+=(w+hspacing);
1153 }
1154 }
1155 }
1156
1157 // Horizontal
1158 else{
1159
1160 // Width
1161 if(hints&LAYOUT_FIX_WIDTH) w=child->getWidth();
1162 else if(options&PACK_UNIFORM_WIDTH) w=mw;
1163 else if(hints&LAYOUT_FILL_X) w=right-left;
1164 else w=child->getDefaultWidth();
1165
1166 // Height
1167 if(hints&LAYOUT_FIX_HEIGHT) h=child->getHeight();
1168 else if(options&PACK_UNIFORM_HEIGHT) h=mh;
1169 else if(hints&LAYOUT_FILL_Y) h=bottom-top;
1170 else h=child->getHeightForWidth(w); // Height is a function of width!
1171
1172 // X
1173 if(!((hints&LAYOUT_RIGHT)&&(hints&LAYOUT_CENTER_X))){
1174 if(hints&LAYOUT_CENTER_X) x=left+(right-left-w)/2;
1175 else if(hints&LAYOUT_RIGHT) x=right-w;
1176 else x=left;
1177 }
1178
1179 // Y
1180 if(!((hints&LAYOUT_BOTTOM)&&(hints&LAYOUT_CENTER_Y))){
1181 if(hints&LAYOUT_CENTER_Y) y=top+(bottom-top-h)/2;
1182 else if(hints&LAYOUT_SIDE_BOTTOM){ // Bottom
1183 y=bottom-h;
1184 bottom-=(h+vspacing);
1185 }
1186 else{ // Top
1187 y=top;
1188 top+=(h+vspacing);
1189 }
1190 }
1191 }
1192 child->position(x,y,w,h);
1193 }
1194 }
1195 flags&=~FLAG_DIRTY;
1196 }
1197
1198
1199 // Update value from a message
onCmdSetStringValue(FXObject *,FXSelector,void * ptr)1200 long FXTopWindow::onCmdSetStringValue(FXObject*,FXSelector,void* ptr){
1201 setTitle(*((FXString*)ptr));
1202 return 1;
1203 }
1204
1205
1206 // Obtain value from text field
onCmdGetStringValue(FXObject *,FXSelector,void * ptr)1207 long FXTopWindow::onCmdGetStringValue(FXObject*,FXSelector,void* ptr){
1208 *((FXString*)ptr)=getTitle();
1209 return 1;
1210 }
1211
1212
1213 // Update icon from a message
onCmdSetIconValue(FXObject *,FXSelector,void * ptr)1214 long FXTopWindow::onCmdSetIconValue(FXObject*,FXSelector,void* ptr){
1215 setMiniIcon(*((FXIcon**)ptr));
1216 return 1;
1217 }
1218
1219
1220 // Obtain icon from text field
onCmdGetIconValue(FXObject *,FXSelector,void * ptr)1221 long FXTopWindow::onCmdGetIconValue(FXObject*,FXSelector,void* ptr){
1222 *((FXIcon**)ptr)=getMiniIcon();
1223 return 1;
1224 }
1225
1226
1227 // Maximize the window
onCmdMaximize(FXObject *,FXSelector,void *)1228 long FXTopWindow::onCmdMaximize(FXObject*,FXSelector,void*){
1229 maximize(TRUE);
1230 return 1;
1231 }
1232
1233
1234 // Minimize or iconify the window
onCmdMinimize(FXObject *,FXSelector,void *)1235 long FXTopWindow::onCmdMinimize(FXObject*,FXSelector,void*){
1236 minimize(TRUE);
1237 return 1;
1238 }
1239
1240
1241 // Restore the window
onCmdRestore(FXObject *,FXSelector,void *)1242 long FXTopWindow::onCmdRestore(FXObject*,FXSelector,void*){
1243 restore(TRUE);
1244 return 1;
1245 }
1246
1247
1248 // Close window; ask target before doing close
onCmdClose(FXObject *,FXSelector,void *)1249 long FXTopWindow::onCmdClose(FXObject*,FXSelector,void*){
1250 close(TRUE);
1251 return 1;
1252 }
1253
1254
1255 // Focus moved up
onFocusUp(FXObject *,FXSelector,void * ptr)1256 long FXTopWindow::onFocusUp(FXObject*,FXSelector,void* ptr){
1257 FXWindow *child,*c;
1258 FXint cury,childy;
1259 if(getFocus()){
1260 cury=getFocus()->getY();
1261 while(1){
1262 child=NULL;
1263 childy=-10000000;
1264 for(c=getFirst(); c; c=c->getNext()){
1265 if(c->shown() && c->getY()<cury && childy<c->getY()){ childy=c->getY(); child=c; }
1266 }
1267 if(!child) return 0;
1268 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1269 if(child->handle(this,FXSEL(SEL_FOCUS_UP,0),ptr)) return 1;
1270 cury=childy;
1271 }
1272 }
1273 else{
1274 child=getLast();
1275 while(child){
1276 if(child->shown()){
1277 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1278 if(child->handle(this,FXSEL(SEL_FOCUS_UP,0),ptr)) return 1;
1279 }
1280 child=child->getPrev();
1281 }
1282 }
1283 return 0;
1284 }
1285
1286
1287 // Focus moved down
onFocusDown(FXObject *,FXSelector,void * ptr)1288 long FXTopWindow::onFocusDown(FXObject*,FXSelector,void* ptr){
1289 FXWindow *child,*c;
1290 FXint cury,childy;
1291 if(getFocus()){
1292 cury=getFocus()->getY();
1293 while(1){
1294 child=NULL;
1295 childy=10000000;
1296 for(c=getFirst(); c; c=c->getNext()){
1297 if(c->shown() && cury<c->getY() && c->getY()<childy){ childy=c->getY(); child=c; }
1298 }
1299 if(!child) return 0;
1300 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1301 if(child->handle(this,FXSEL(SEL_FOCUS_DOWN,0),ptr)) return 1;
1302 cury=childy;
1303 }
1304 }
1305 else{
1306 child=getFirst();
1307 while(child){
1308 if(child->shown()){
1309 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1310 if(child->handle(this,FXSEL(SEL_FOCUS_DOWN,0),ptr)) return 1;
1311 }
1312 child=child->getNext();
1313 }
1314 }
1315 return 0;
1316 }
1317
1318
1319 // Focus moved to left
onFocusLeft(FXObject *,FXSelector,void * ptr)1320 long FXTopWindow::onFocusLeft(FXObject*,FXSelector,void* ptr){
1321 FXWindow *child,*c;
1322 FXint curx,childx;
1323 if(getFocus()){
1324 curx=getFocus()->getX();
1325 while(1){
1326 child=NULL;
1327 childx=-10000000;
1328 for(c=getFirst(); c; c=c->getNext()){
1329 if(c->shown() && c->getX()<curx && childx<c->getX()){ childx=c->getX(); child=c; }
1330 }
1331 if(!child) return 0;
1332 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1333 if(child->handle(this,FXSEL(SEL_FOCUS_LEFT,0),ptr)) return 1;
1334 curx=childx;
1335 }
1336 }
1337 else{
1338 child=getLast();
1339 while(child){
1340 if(child->shown()){
1341 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1342 if(child->handle(this,FXSEL(SEL_FOCUS_LEFT,0),ptr)) return 1;
1343 }
1344 child=child->getPrev();
1345 }
1346 }
1347 return 0;
1348 }
1349
1350
1351 // Focus moved to right
onFocusRight(FXObject *,FXSelector,void * ptr)1352 long FXTopWindow::onFocusRight(FXObject*,FXSelector,void* ptr){
1353 FXWindow *child,*c;
1354 FXint curx,childx;
1355 if(getFocus()){
1356 curx=getFocus()->getX();
1357 while(1){
1358 child=NULL;
1359 childx=10000000;
1360 for(c=getFirst(); c; c=c->getNext()){
1361 if(c->shown() && curx<c->getX() && c->getX()<childx){ childx=c->getX(); child=c; }
1362 }
1363 if(!child) return 0;
1364 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1365 if(child->handle(this,FXSEL(SEL_FOCUS_RIGHT,0),ptr)) return 1;
1366 curx=childx;
1367 }
1368 }
1369 else{
1370 child=getFirst();
1371 while(child){
1372 if(child->shown()){
1373 if(child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
1374 if(child->handle(this,FXSEL(SEL_FOCUS_RIGHT,0),ptr)) return 1;
1375 }
1376 child=child->getNext();
1377 }
1378 }
1379 return 0;
1380 }
1381
1382
1383
1384 // Change regular icon
setIcon(FXIcon * ic)1385 void FXTopWindow::setIcon(FXIcon* ic){
1386 if(icon!=ic){
1387 icon=ic;
1388 if(xid) seticons();
1389 }
1390 }
1391
1392
1393 // Change mini icon
setMiniIcon(FXIcon * ic)1394 void FXTopWindow::setMiniIcon(FXIcon *ic){
1395 if(miniIcon!=ic){
1396 miniIcon=ic;
1397 if(xid) seticons();
1398 }
1399 }
1400
1401
1402 // Set new window title
setTitle(const FXString & name)1403 void FXTopWindow::setTitle(const FXString& name){
1404 if(title!=name){
1405 title=name;
1406 if(xid) settitle();
1407 }
1408 }
1409
1410
1411 // Change packing hints
setPackingHints(FXuint ph)1412 void FXTopWindow::setPackingHints(FXuint ph){
1413 FXuint opts=(options&~(PACK_UNIFORM_HEIGHT|PACK_UNIFORM_WIDTH)) | (ph&(PACK_UNIFORM_HEIGHT|PACK_UNIFORM_WIDTH));
1414 if(opts!=options){
1415 options=opts;
1416 recalc();
1417 update();
1418 }
1419 }
1420
1421
1422 // Get packing hints
getPackingHints() const1423 FXuint FXTopWindow::getPackingHints() const {
1424 return (options&(PACK_UNIFORM_HEIGHT|PACK_UNIFORM_WIDTH));
1425 }
1426
1427
1428 // Change top padding
setPadTop(FXint pt)1429 void FXTopWindow::setPadTop(FXint pt){
1430 if(padtop!=pt){
1431 padtop=pt;
1432 recalc();
1433 update();
1434 }
1435 }
1436
1437
1438 // Change bottom padding
setPadBottom(FXint pb)1439 void FXTopWindow::setPadBottom(FXint pb){
1440 if(padbottom!=pb){
1441 padbottom=pb;
1442 recalc();
1443 update();
1444 }
1445 }
1446
1447
1448 // Change left padding
setPadLeft(FXint pl)1449 void FXTopWindow::setPadLeft(FXint pl){
1450 if(padleft!=pl){
1451 padleft=pl;
1452 recalc();
1453 update();
1454 }
1455 }
1456
1457
1458 // Change right padding
setPadRight(FXint pr)1459 void FXTopWindow::setPadRight(FXint pr){
1460 if(padright!=pr){
1461 padright=pr;
1462 recalc();
1463 update();
1464 }
1465 }
1466
1467
1468 // Change horizontal spacing
setHSpacing(FXint hs)1469 void FXTopWindow::setHSpacing(FXint hs){
1470 if(hspacing!=hs){
1471 hspacing=hs;
1472 recalc();
1473 update();
1474 }
1475 }
1476
1477
1478 // Change vertical spacing
setVSpacing(FXint vs)1479 void FXTopWindow::setVSpacing(FXint vs){
1480 if(vspacing!=vs){
1481 vspacing=vs;
1482 recalc();
1483 update();
1484 }
1485 }
1486
1487 // Save object to stream
save(FXStream & store) const1488 void FXTopWindow::save(FXStream& store) const {
1489 FXShell::save(store);
1490 store << title;
1491 store << icon;
1492 store << miniIcon;
1493 store << padtop << padbottom << padleft << padright;
1494 store << hspacing << vspacing;
1495 }
1496
1497
1498 // Load object from stream
load(FXStream & store)1499 void FXTopWindow::load(FXStream& store){
1500 FXShell::load(store);
1501 store >> title;
1502 store >> icon;
1503 store >> miniIcon;
1504 store >> padtop >> padbottom >> padleft >> padright;
1505 store >> hspacing >> vspacing;
1506 }
1507
1508
1509 // Remove this one from toplevel window list
~FXTopWindow()1510 FXTopWindow::~FXTopWindow(){
1511 #ifdef WIN32
1512 HICON icold;
1513 if((icold=(HICON)SendMessage((HWND)xid,WM_SETICON,ICON_BIG,0))!=0){
1514 DestroyIcon(icold);
1515 }
1516 if((icold=(HICON)SendMessage((HWND)xid,WM_SETICON,ICON_SMALL,0))!=0){
1517 DestroyIcon(icold);
1518 }
1519 #endif
1520 icon=(FXIcon*)-1L;
1521 miniIcon=(FXIcon*)-1L;
1522 }
1523
1524 }
1525