/* Cockos SWELL (Simple/Small Win32 Emulation Layer for Linux/OSX) Copyright (C) 2006 and later, Cockos, Inc. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #ifndef SWELL_PROVIDED_BY_APP #include "swell.h" #include "swell-dlggen.h" #include "../ptrlist.h" static HMENU g_swell_defaultmenu,g_swell_defaultmenumodal; bool SWELL_owned_windows_levelincrease=false; #include "swell-internal.h" static SWELL_DialogResourceIndex *resById(SWELL_DialogResourceIndex *reshead, const char *resid) { SWELL_DialogResourceIndex *p=reshead; while (p) { if (p->resid == resid) return p; p=p->_next; } return 0; } // keep list of modal dialogs struct modalDlgRet { HWND hwnd; bool has_ret; int ret; }; static WDL_PtrList s_modalDialogs; bool IsModalDialogBox(HWND hwnd) { if (WDL_NOT_NORMALLY(!hwnd)) return false; int a = s_modalDialogs.GetSize(); while (a-- > 0) { modalDlgRet *r = s_modalDialogs.Get(a); if (r && r->hwnd == hwnd) return true; } return false; } HWND DialogBoxIsActive() { int a = s_modalDialogs.GetSize(); while (a-- > 0) { modalDlgRet *r = s_modalDialogs.Get(a); if (r && !r->has_ret && r->hwnd) return r->hwnd; } return NULL; } static SWELL_OSWINDOW s_spare; static RECT s_spare_rect; static UINT_PTR s_spare_timer; static int s_spare_style; void swell_dlg_destroyspare() { if (s_spare_timer) { KillTimer(NULL,s_spare_timer); s_spare_timer=0; } if (s_spare) { #ifdef SWELL_TARGET_GDK gdk_window_destroy(s_spare); #endif s_spare=NULL; } } static void spareTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwtime) { swell_dlg_destroyspare(); } static int s_last_dlgret; void EndDialog(HWND wnd, int ret) { if (WDL_NOT_NORMALLY(!wnd)) return; int a = s_modalDialogs.GetSize(); while (a-->0) { modalDlgRet *r = s_modalDialogs.Get(a); if (r && r->hwnd == wnd) { r->ret = ret; if (r->has_ret) return; r->has_ret=true; } } if (!wnd->m_hashaddestroy) { void RecurseDestroyWindow(HWND); SendMessage(wnd,WM_DESTROY,0,0); #ifndef SWELL_NO_SPARE_MODALDLG if (wnd->m_oswindow && wnd->m_visible) { swell_dlg_destroyspare(); s_spare_rect = wnd->m_position; s_spare_style = wnd->m_style; s_spare = wnd->m_oswindow; wnd->m_oswindow = NULL; s_spare_timer = SetTimer(NULL,0, swell_is_app_inactive()>0 ? 500 : 100, spareTimer); } #endif RecurseDestroyWindow(wnd); } s_last_dlgret = ret; } int SWELL_DialogBox(SWELL_DialogResourceIndex *reshead, const char *resid, HWND parent, DLGPROC dlgproc, LPARAM param) { SWELL_DialogResourceIndex *p=resById(reshead,resid); if (resid) // allow modal dialogs to be created without template { if (!p||(p->windowTypeFlags&SWELL_DLG_WS_CHILD)) return -1; } else if (parent) { resid = (const char *)(INT_PTR)(0x400002); // force non-child, force no minimize box } int ret=-1; s_last_dlgret = -1; HWND hwnd = SWELL_CreateDialog(reshead,resid,parent,dlgproc,param); // create dialog if (hwnd) { hwnd->Retain(); void SWELL_OnNavigationFocus(HWND ch); HWND SWELL_GetFocusedChild(HWND h); SWELL_OnNavigationFocus(SWELL_GetFocusedChild(hwnd)); ReleaseCapture(); // force end of any captures WDL_PtrKeyedArray restwnds; extern HWND__ *SWELL_topwindows; HWND a = SWELL_topwindows; while (a) { if (a!=hwnd) { int f=0; if (a->m_enabled) { EnableWindow(a,FALSE); f|=1; } if (a->m_israised) { SWELL_SetWindowLevel(a,0); f|=2; } if (f) restwnds.AddUnsorted((INT_PTR)a,f); } a = a->m_next; } restwnds.Resort(); SWELL_SetWindowLevel(hwnd,1); modalDlgRet r = { hwnd,false, -1 }; s_modalDialogs.Add(&r); if (s_spare && s_spare_style == hwnd->m_style) { if (s_spare_timer) { KillTimer(NULL,s_spare_timer); s_spare_timer = 0; } SWELL_OSWINDOW w = s_spare; s_spare = NULL; int flags = 0; const int dw = (hwnd->m_position.right-hwnd->m_position.left) - (s_spare_rect.right - s_spare_rect.left); const int dh = (hwnd->m_position.bottom-hwnd->m_position.top) - (s_spare_rect.bottom - s_spare_rect.top); if (hwnd->m_has_had_position) flags |= 1; if (dw || dh) flags |= 2; if (flags == 2) { // center on the old window hwnd->m_position.right -= hwnd->m_position.left; hwnd->m_position.bottom -= hwnd->m_position.top; hwnd->m_position.left = s_spare_rect.left - dw/2; hwnd->m_position.top = s_spare_rect.top - dh/2; hwnd->m_position.right += hwnd->m_position.left; hwnd->m_position.bottom += hwnd->m_position.top; flags = 3; } if (flags) { if (flags&2) swell_oswindow_begin_resize(w); swell_oswindow_resize(w, flags, hwnd->m_position); } hwnd->m_oswindow = w; if (!flags) { hwnd->m_has_had_position = true; hwnd->m_position = s_spare_rect; if (!hwnd->m_hashaddestroy) { void swell_recalcMinMaxInfo(HWND hwnd); swell_recalcMinMaxInfo(hwnd); } } swell_oswindow_focus(hwnd); ShowWindow(hwnd,SW_SHOWNA); InvalidateRect(hwnd,NULL,FALSE); } else { swell_dlg_destroyspare(); ShowWindow(hwnd,SW_SHOW); } while (!r.has_ret && !hwnd->m_hashaddestroy) { void SWELL_RunMessageLoop(); SWELL_RunMessageLoop(); Sleep(10); } ret=r.ret; s_modalDialogs.DeletePtr(&r); a = SWELL_topwindows; while (a) { if (a != hwnd) { int f = restwnds.Get((INT_PTR)a); if (!a->m_enabled && (f&1)) EnableWindow(a,TRUE); if (!a->m_israised && (f&2)) SWELL_SetWindowLevel(a,1); } a = a->m_next; } hwnd->Release(); } else { ret = s_last_dlgret; // SWELL_CreateDialog() failed, implies WM_INITDIALOG could have called EndDialog() } // while in list, do something return ret; } HWND SWELL_CreateDialog(SWELL_DialogResourceIndex *reshead, const char *resid, HWND parent, DLGPROC dlgproc, LPARAM param) { int forceStyles=0; // 1=resizable, 2=no minimize, 4=no close bool forceNonChild=false; if ((((INT_PTR)resid)&~0xf)==0x400000) { forceStyles = (int) (((INT_PTR)resid)&0xf); if (forceStyles) forceNonChild=true; resid=0; } SWELL_DialogResourceIndex *p=resById(reshead,resid); if (!p&&resid) return 0; RECT r={0,0,SWELL_UI_SCALE(p ? p->width : 300), SWELL_UI_SCALE(p ? p->height : 200) }; HWND owner=NULL; if (!forceNonChild && parent && (!p || (p->windowTypeFlags&SWELL_DLG_WS_CHILD))) { } else { owner = parent; parent = NULL; // top level window } HWND__ *h = new HWND__(parent,0,&r,NULL,false,NULL,NULL, owner); if (forceNonChild || (p && !(p->windowTypeFlags&SWELL_DLG_WS_CHILD))) { if ((forceStyles&1) || (p && (p->windowTypeFlags&SWELL_DLG_WS_RESIZABLE))) h->m_style |= WS_THICKFRAME|WS_CAPTION; else h->m_style |= WS_CAPTION; } else if (!p && !parent) h->m_style |= WS_CAPTION; else if (parent && (!p || (p->windowTypeFlags&SWELL_DLG_WS_CHILD))) h->m_style |= WS_CHILD; if (p) { h->m_style |= p->windowTypeFlags & (WS_CLIPSIBLINGS); if (p->windowTypeFlags&SWELL_DLG_WS_DROPTARGET) h->m_exstyle|=WS_EX_ACCEPTFILES; } h->Retain(); if (p) { p->createFunc(h,p->windowTypeFlags); if (p->title) SetWindowText(h,p->title); h->m_dlgproc = dlgproc; h->m_wndproc = SwellDialogDefaultWindowProc; HWND hFoc=h->m_children; while (hFoc) { if (hFoc->m_wantfocus && hFoc->m_visible && hFoc->m_enabled) { h->m_focused_child = hFoc; // default focus to hFoc, but set focus more aggressively after WM_INITDIALOG if the dlgproc returns 1 break; } hFoc=hFoc->m_next; } if (hFoc) hFoc->Retain(); if (h->m_dlgproc(h,WM_INITDIALOG,(WPARAM)hFoc,param)) { if (hFoc && hFoc->m_wantfocus && hFoc->m_visible && hFoc->m_enabled) { if (!h->m_hashaddestroy && !hFoc->m_hashaddestroy) SetFocus(hFoc); } } if (hFoc) hFoc->Release(); } else { h->m_wndproc = (WNDPROC)dlgproc; h->m_wndproc(h,WM_CREATE,0,param); } HWND rv = h->m_hashaddestroy ? NULL : h; h->Release(); return rv; } HMENU SWELL_GetDefaultWindowMenu() { return g_swell_defaultmenu; } void SWELL_SetDefaultWindowMenu(HMENU menu) { g_swell_defaultmenu=menu; } HMENU SWELL_GetDefaultModalWindowMenu() { return g_swell_defaultmenumodal; } void SWELL_SetDefaultModalWindowMenu(HMENU menu) { g_swell_defaultmenumodal=menu; } SWELL_DialogResourceIndex *SWELL_curmodule_dialogresource_head; // this eventually will go into a per-module stub file #endif