1 /* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX)
2 Copyright (C) 2006 and later, Cockos, Inc.
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
21 #ifndef SWELL_PROVIDED_BY_APP
24 #include "swell-dlggen.h"
26 #include "../ptrlist.h"
28 static HMENU g_swell_defaultmenu
,g_swell_defaultmenumodal
;
30 void (*SWELL_DDrop_onDragLeave
)();
31 void (*SWELL_DDrop_onDragOver
)(POINT pt
);
32 void (*SWELL_DDrop_onDragEnter
)(void *hGlobal
, POINT pt
);
33 const char* (*SWELL_DDrop_getDroppedFileTargetPath
)(const char* extension
);
35 bool SWELL_owned_windows_levelincrease
=false;
37 #include "swell-internal.h"
39 static SWELL_DialogResourceIndex
*resById(SWELL_DialogResourceIndex
*reshead
, const char *resid
)
41 SWELL_DialogResourceIndex
*p
=reshead
;
44 if (p
->resid
== resid
) return p
;
50 // keep list of modal dialogs
58 static WDL_PtrList
<modalDlgRet
> s_modalDialogs
;
60 bool IsModalDialogBox(HWND hwnd
)
62 if (!hwnd
) return false;
63 int a
= s_modalDialogs
.GetSize();
66 modalDlgRet
*r
= s_modalDialogs
.Get(a
);
67 if (r
&& r
->hwnd
== hwnd
) return true;
72 HWND
DialogBoxIsActive()
74 int a
= s_modalDialogs
.GetSize();
77 modalDlgRet
*r
= s_modalDialogs
.Get(a
);
78 if (r
&& !r
->has_ret
&& r
->hwnd
) return r
->hwnd
;
83 static SWELL_OSWINDOW s_spare
;
84 static RECT s_spare_rect
;
85 static UINT_PTR s_spare_timer
;
86 static int s_spare_style
;
88 void swell_dlg_destroyspare()
92 KillTimer(NULL
,s_spare_timer
);
97 #ifdef SWELL_TARGET_GDK
98 gdk_window_destroy(s_spare
);
104 static void spareTimer(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwtime
)
106 swell_dlg_destroyspare();
109 static int s_last_dlgret
;
111 void EndDialog(HWND wnd
, int ret
)
115 int a
= s_modalDialogs
.GetSize();
118 modalDlgRet
*r
= s_modalDialogs
.Get(a
);
119 if (r
&& r
->hwnd
== wnd
)
122 if (r
->has_ret
) return;
128 if (!wnd
->m_hashaddestroy
)
130 void RecurseDestroyWindow(HWND
);
131 SendMessage(wnd
,WM_DESTROY
,0,0);
132 #ifndef SWELL_NO_SPARE_MODALDLG
133 if (wnd
->m_oswindow
&& wnd
->m_visible
)
135 swell_dlg_destroyspare();
136 GetWindowRect(wnd
,&s_spare_rect
);
137 s_spare_style
= wnd
->m_style
;
138 s_spare
= wnd
->m_oswindow
;
139 wnd
->m_oswindow
= NULL
;
140 s_spare_timer
= SetTimer(NULL
,0,
141 swell_app_is_inactive
? 500 : 100,
145 RecurseDestroyWindow(wnd
);
150 int SWELL_DialogBox(SWELL_DialogResourceIndex
*reshead
, const char *resid
, HWND parent
, DLGPROC dlgproc
, LPARAM param
)
152 SWELL_DialogResourceIndex
*p
=resById(reshead
,resid
);
153 if (resid
) // allow modal dialogs to be created without template
155 if (!p
||(p
->windowTypeFlags
&SWELL_DLG_WS_CHILD
)) return -1;
159 resid
= (const char *)(INT_PTR
)(0x400002); // force non-child, force no minimize box
165 HWND hwnd
= SWELL_CreateDialog(reshead
,resid
,parent
,dlgproc
,param
);
170 ReleaseCapture(); // force end of any captures
172 WDL_PtrKeyedArray
<int> restwnds
;
173 extern HWND__
*SWELL_topwindows
;
174 HWND a
= SWELL_topwindows
;
180 if (a
->m_enabled
) { EnableWindow(a
,FALSE
); f
|=1; }
181 if (a
->m_israised
) { SWELL_SetWindowLevel(a
,0); f
|=2; }
182 if (f
) restwnds
.AddUnsorted((INT_PTR
)a
,f
);
187 SWELL_SetWindowLevel(hwnd
,1);
189 modalDlgRet r
= { hwnd
,false, -1 };
190 s_modalDialogs
.Add(&r
);
192 if (s_spare
&& s_spare_style
== hwnd
->m_style
)
196 KillTimer(NULL
,s_spare_timer
);
199 SWELL_OSWINDOW w
= s_spare
;
203 const int dw
= (hwnd
->m_position
.right
-hwnd
->m_position
.left
) -
204 (s_spare_rect
.right
- s_spare_rect
.left
);
205 const int dh
= (hwnd
->m_position
.bottom
-hwnd
->m_position
.top
) -
206 (s_spare_rect
.bottom
- s_spare_rect
.top
);
208 if (hwnd
->m_has_had_position
) flags
|= 1;
209 if (dw
|| dh
) flags
|= 2;
213 // center on the old window
214 hwnd
->m_position
.right
-= hwnd
->m_position
.left
;
215 hwnd
->m_position
.bottom
-= hwnd
->m_position
.top
;
216 hwnd
->m_position
.left
= s_spare_rect
.left
- dw
/2;
217 hwnd
->m_position
.top
= s_spare_rect
.top
- dh
/2;
218 hwnd
->m_position
.right
+= hwnd
->m_position
.left
;
219 hwnd
->m_position
.bottom
+= hwnd
->m_position
.top
;
225 if (flags
&2) swell_oswindow_begin_resize(w
);
226 swell_oswindow_resize(w
, flags
, hwnd
->m_position
);
228 hwnd
->m_oswindow
= w
;
229 ShowWindow(hwnd
,SW_SHOWNA
);
233 swell_dlg_destroyspare();
234 ShowWindow(hwnd
,SW_SHOW
);
237 while (!r
.has_ret
&& !hwnd
->m_hashaddestroy
)
239 void SWELL_RunMessageLoop();
240 SWELL_RunMessageLoop();
244 s_modalDialogs
.DeletePtr(&r
);
246 a
= SWELL_topwindows
;
251 int f
= restwnds
.Get((INT_PTR
)a
);
252 if (!a
->m_enabled
&& (f
&1)) EnableWindow(a
,TRUE
);
253 if (!a
->m_israised
&& (f
&2)) SWELL_SetWindowLevel(a
,1);
261 ret
= s_last_dlgret
; // SWELL_CreateDialog() failed, implies WM_INITDIALOG could have called EndDialog()
263 // while in list, do something
267 HWND
SWELL_CreateDialog(SWELL_DialogResourceIndex
*reshead
, const char *resid
, HWND parent
, DLGPROC dlgproc
, LPARAM param
)
269 int forceStyles
=0; // 1=resizable, 2=no minimize, 4=no close
270 bool forceNonChild
=false;
271 if ((((INT_PTR
)resid
)&~0xf)==0x400000)
273 forceStyles
= (int) (((INT_PTR
)resid
)&0xf);
274 if (forceStyles
) forceNonChild
=true;
277 SWELL_DialogResourceIndex
*p
=resById(reshead
,resid
);
278 if (!p
&&resid
) return 0;
280 RECT r
={0,0,SWELL_UI_SCALE(p
? p
->width
: 300), SWELL_UI_SCALE(p
? p
->height
: 200) };
283 if (!forceNonChild
&& parent
&& (!p
|| (p
->windowTypeFlags
&SWELL_DLG_WS_CHILD
)))
289 parent
= NULL
; // top level window
292 HWND__
*h
= new HWND__(parent
,0,&r
,NULL
,false,NULL
,NULL
, owner
);
293 if (forceNonChild
|| (p
&& !(p
->windowTypeFlags
&SWELL_DLG_WS_CHILD
)))
295 if ((forceStyles
&1) || (p
&& (p
->windowTypeFlags
&SWELL_DLG_WS_RESIZABLE
)))
296 h
->m_style
|= WS_THICKFRAME
|WS_CAPTION
;
297 else h
->m_style
|= WS_CAPTION
;
299 else if (!p
&& !parent
) h
->m_style
|= WS_CAPTION
;
300 else if (parent
&& (!p
|| (p
->windowTypeFlags
&SWELL_DLG_WS_CHILD
))) h
->m_style
|= WS_CHILD
;
306 p
->createFunc(h
,p
->windowTypeFlags
);
307 if (p
->title
) SetWindowText(h
,p
->title
);
309 h
->m_dlgproc
= dlgproc
;
310 h
->m_wndproc
= SwellDialogDefaultWindowProc
;
312 HWND hFoc
=h
->m_children
;
315 if (hFoc
->m_wantfocus
&& hFoc
->m_visible
&& hFoc
->m_enabled
)
317 h
->m_focused_child
= hFoc
; // default focus to hFoc, but set focus more aggressively after WM_INITDIALOG if the dlgproc returns 1
323 if (hFoc
) hFoc
->Retain();
325 if (h
->m_dlgproc(h
,WM_INITDIALOG
,(WPARAM
)hFoc
,param
))
327 if (hFoc
&& hFoc
->m_wantfocus
&& hFoc
->m_visible
&& hFoc
->m_enabled
)
329 if (!h
->m_hashaddestroy
&& !hFoc
->m_hashaddestroy
)
334 if (hFoc
) hFoc
->Release();
338 h
->m_wndproc
= (WNDPROC
)dlgproc
;
339 h
->m_wndproc(h
,WM_CREATE
,0,param
);
342 HWND rv
= h
->m_hashaddestroy
? NULL
: h
;
348 HMENU
SWELL_GetDefaultWindowMenu() { return g_swell_defaultmenu
; }
349 void SWELL_SetDefaultWindowMenu(HMENU menu
)
351 g_swell_defaultmenu
=menu
;
353 HMENU
SWELL_GetDefaultModalWindowMenu()
355 return g_swell_defaultmenumodal
;
357 void SWELL_SetDefaultModalWindowMenu(HMENU menu
)
359 g_swell_defaultmenumodal
=menu
;
364 SWELL_DialogResourceIndex
*SWELL_curmodule_dialogresource_head
; // this eventually will go into a per-module stub file