Merge pull request #110 from tesselode/fixes
[wdl/wdl-ol.git] / WDL / swell / swell-dlg-generic.cpp
blobb5eca28fa6eaedf1054531f7564783aad4110479
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
23 #include "swell.h"
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;
42 while (p)
44 if (p->resid == resid) return p;
45 p=p->_next;
47 return 0;
50 // keep list of modal dialogs
51 struct modalDlgRet {
52 HWND hwnd;
53 bool has_ret;
54 int ret;
58 static WDL_PtrList<modalDlgRet> s_modalDialogs;
60 bool IsModalDialogBox(HWND hwnd)
62 if (!hwnd) return false;
63 int a = s_modalDialogs.GetSize();
64 while (a-- > 0)
66 modalDlgRet *r = s_modalDialogs.Get(a);
67 if (r && r->hwnd == hwnd) return true;
69 return false;
72 HWND DialogBoxIsActive()
74 int a = s_modalDialogs.GetSize();
75 while (a-- > 0)
77 modalDlgRet *r = s_modalDialogs.Get(a);
78 if (r && !r->has_ret && r->hwnd) return r->hwnd;
80 return NULL;
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()
90 if (s_spare_timer)
92 KillTimer(NULL,s_spare_timer);
93 s_spare_timer=0;
95 if (s_spare)
97 #ifdef SWELL_TARGET_GDK
98 gdk_window_destroy(s_spare);
99 #endif
100 s_spare=NULL;
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)
113 if (!wnd) return;
115 int a = s_modalDialogs.GetSize();
116 while (a-->0)
118 modalDlgRet *r = s_modalDialogs.Get(a);
119 if (r && r->hwnd == wnd)
121 r->ret = ret;
122 if (r->has_ret) return;
124 r->has_ret=true;
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,
142 spareTimer);
144 #endif
145 RecurseDestroyWindow(wnd);
147 s_last_dlgret = ret;
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;
157 else if (parent)
159 resid = (const char *)(INT_PTR)(0x400002); // force non-child, force no minimize box
163 int ret=-1;
164 s_last_dlgret = -1;
165 HWND hwnd = SWELL_CreateDialog(reshead,resid,parent,dlgproc,param);
166 // create dialog
167 if (hwnd)
169 hwnd->Retain();
170 ReleaseCapture(); // force end of any captures
172 WDL_PtrKeyedArray<int> restwnds;
173 extern HWND__ *SWELL_topwindows;
174 HWND a = SWELL_topwindows;
175 while (a)
177 if (a!=hwnd)
179 int f=0;
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);
184 a = a->m_next;
186 restwnds.Resort();
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)
194 if (s_spare_timer)
196 KillTimer(NULL,s_spare_timer);
197 s_spare_timer = 0;
199 SWELL_OSWINDOW w = s_spare;
200 s_spare = NULL;
202 int flags = 0;
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;
211 if (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;
220 flags = 3;
223 if (flags)
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);
231 else
233 swell_dlg_destroyspare();
234 ShowWindow(hwnd,SW_SHOW);
237 while (!r.has_ret && !hwnd->m_hashaddestroy)
239 void SWELL_RunMessageLoop();
240 SWELL_RunMessageLoop();
241 Sleep(10);
243 ret=r.ret;
244 s_modalDialogs.DeletePtr(&r);
246 a = SWELL_topwindows;
247 while (a)
249 if (a != hwnd)
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);
255 a = a->m_next;
257 hwnd->Release();
259 else
261 ret = s_last_dlgret; // SWELL_CreateDialog() failed, implies WM_INITDIALOG could have called EndDialog()
263 // while in list, do something
264 return ret;
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;
275 resid=0;
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) };
281 HWND owner=NULL;
283 if (!forceNonChild && parent && (!p || (p->windowTypeFlags&SWELL_DLG_WS_CHILD)))
286 else
288 owner = parent;
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;
302 h->Retain();
304 if (p)
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;
313 while (hFoc)
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
318 break;
320 hFoc=hFoc->m_next;
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)
330 SetFocus(hFoc);
334 if (hFoc) hFoc->Release();
336 else
338 h->m_wndproc = (WNDPROC)dlgproc;
339 h->m_wndproc(h,WM_CREATE,0,param);
342 HWND rv = h->m_hashaddestroy ? NULL : h;
343 h->Release();
344 return rv;
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
366 #endif