Jules, you fixed this issue in version 1.38, but there are still some problems.
First of all the last-non-fullscreen-position gets messed up if you do the following:
- disable the native title bar
- maximize the ResizeableWindow
- enable the native title bar
- demaximize the ResizeableWindow
=> the window has now an other position and size than before the maximize.
This doesn’t happen if it’s done the other way around:
- enable the native title bar
- maximize the ResizeableWindow
- disable the native title bar
- demaximize the ResizeableWindow
=> everything is okay
The next issues are about the basic handling of maximize/minimize in the platform specific code.
First is the juce_updateMultiMonitorInfo(…) in juce_linux_Windowing.cpp. The handling of clipToWorkArea is totally missing and if no Xinerama is present or not used it falls back to only add the defaultscreen even if more screens are present. So I suggest to change:
if (monitorCoords.size() == 0)
#endif
{
monitorCoords.add (Rectangle (0, 0,
DisplayWidth (display, DefaultScreen (display)),
DisplayHeight (display, DefaultScreen (display))));
}
to this:
[code] if (monitorCoords.size() == 0)
#endif
{
int numMonitors = ScreenCount(display);
Atom hints = None;
if (clipToWorkArea)
hints = XInternAtom (display, "_NET_WORKAREA", True);
for (int i = 0; i < numMonitors; i++)
{
if (clipToWorkArea && hints != None)
{
Window root = RootWindow (display, i);
unsigned long nitems, bytesLeft;
Atom actualType;
int actualFormat;
long* workarea = 0;
if (XGetWindowProperty (display, root, hints, 0, 4, False,
XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft,
(unsigned char**) &workarea) == Success)
{
if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4)
monitorCoords.add(Rectangle(workarea[0], workarea[1], workarea[2], workarea[3]));
XFree (workarea);
}
}
else
monitorCoords.add(Rectangle(0, 0, DisplayWidth(display, i), DisplayHeight(display, i)));
}
}[/code]
With this change LinuxComponentPeer::setFullScreen(…) would no longer expand the window to the total screensize but to the workarea like it’s supposed to. A better way may be to maximize the window would be to set _NET_WM_STATE_MAXIMIZED_VERT and _NET_WM_STATE_MAXIMIZED_HORZ for it, like the ShowWindow(hwnd, SW_SHOWMAXIMIZED) on windows if the window has a native title bar.
I tried to do this but couldn’t get it work like I want it to, perhaps because I play around with Xlib just since 3 days.
Second is the XSetTransientForHint(display, wndH, RootWindow(display, DefaultScreen(display))) in LinuxComponentPeer::createWindow(). If you set all windows to be transient for the rootwindow some window manager will handle the window wrong. Gnome seems to be unaffected but wmii will get it wrong. They way JUCE currently handles it is not conform with the ICCCM. For example in the JUCE case only modal dialogs or similar should get the transient-for hint. But they should not be transient for the rootwindow but for the applications mainwindow.
I know that this is not easy to solve, may involve many changes in the code and it is not that important, but I want to point out at this.
Third is the sysmenu on windows. With the following changes the sysmenu will be full functional for minimize/maximize with and without native title bar:
DocumentWindow::getDesktopWindowStyleFlags()
[code] int flags = ResizableWindow::getDesktopWindowStyleFlags();
// photon:
// at least win32 needs this, because these flags define the
// items in the sysmenu
#if (JUCE_WIN32 == 0)
if ((flags & ComponentPeer::windowHasTitleBar) != 0)
#endif
{[/code]
Win32ComponentPeer::setFullScreen(…)
[code] if (! fullScreen)
{
// photon:
// remove SW_SHOWMAXIMIZED from the window
if ((styleFlags & windowHasTitleBar) != 0)
ShowWindow (hwnd, SW_SHOWNORMAL);
if (! lastNonFullscreenBounds.isEmpty())[/code]
Win32ComponentPeer::createWindow()
[code] if ((styleFlags & windowHasTitleBar) != 0)
{
[…]
}
else
{
// photon:
// set type corresponding styleFlags to get the right items in the sysmenu
type |= WS_POPUP | WS_SYSMENU;
if ((styleFlags & windowHasMinimiseButton) != 0)
type |= WS_MINIMIZEBOX;
if ((styleFlags & windowHasMaximiseButton) != 0)
type |= WS_MAXIMIZEBOX;
if ((styleFlags & windowAppearsOnTaskbar) == 0)
exstyle |= WS_EX_TOOLWINDOW;
else
exstyle |= WS_EX_APPWINDOW;
}[/code]
Win32ComponentPeer::peerWindowProc(…)
[code] case WM_INITMENU:
// photon:
// need to update state of some sysmenu items if there is no native title bar
// because then the os is not aware that this window is maximized in a fake way
if ((styleFlags & windowHasTitleBar) == 0)
{
// xxx the first popup of the sysmenu is unaffected by this after that it works like it should
HMENU hmenu = GetSystemMenu (hwnd, false);
if (isFullScreen())
{
EnableMenuItem (hmenu, SC_RESTORE, MF_BYCOMMAND | MF_ENABLED);
EnableMenuItem (hmenu, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
if (! isMinimised())
EnableMenuItem (hmenu, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
}
}
break;
case WM_SYSCOMMAND:
if ((styleFlags & windowHasTitleBar) != 0)
{
switch (wParam & 0xfff0)
{
case SC_CLOSE:
PostMessage (h, WM_CLOSE, 0, 0);
return 0;
// photon:
// handle this through the peer
case SC_MAXIMIZE:
setFullScreen(true);
return 0;
case SC_RESTORE:
if (isFullScreen())
{
setFullScreen(false);
return 0;
}
break;
case SC_KEYMENU:
if (h == GetCapture())
ReleaseCapture();
break;
}
}
else
{
// photon:
// Now windows can be minimized/maximized/restored via
// sysmenu if window has no native title bar
switch (wParam & 0xfff0)
{
case SC_MINIMIZE:
setMinimised(true);
return 0;
case SC_MAXIMIZE:
setFullScreen(true);
return 0;
case SC_RESTORE:
if (isMinimised())
setMinimised(false);
else if (isFullScreen())
setFullScreen(false);
return 0;
}
}
break;[/code]
Sorry for this long post, perhaps I should have attached a diff rather than post it like this.