From d13c3cbd43bc5e6b459c7df822292cf02ad2c9c4 Mon Sep 17 00:00:00 2001 From: Jeremy Huddleston Date: Wed, 8 Oct 2008 18:39:41 -0700 Subject: [PATCH] XQuartz: Some motion made towards supporting fullscreen. (cherry picked from commit 99be3d68b64059caada739a373e5e01844c776e0) --- hw/xquartz/X11Application.h | 1 + hw/xquartz/X11Application.m | 10 +-- hw/xquartz/X11Controller.m | 6 +- hw/xquartz/darwinEvents.c | 11 +-- hw/xquartz/quartz.c | 118 ++++++++++++++++++++++++-------- hw/xquartz/quartz.h | 3 + hw/xquartz/quartzCommon.h | 1 + miext/rootless/rootlessCommon.h | 12 +++- miext/rootless/rootlessScreen.c | 43 ++++++++++++ miext/rootless/rootlessWindow.c | 102 +++++++++++++++++++++++++++ 10 files changed, 257 insertions(+), 50 deletions(-) diff --git a/hw/xquartz/X11Application.h b/hw/xquartz/X11Application.h index 0caaba83f..4335abc7d 100644 --- a/hw/xquartz/X11Application.h +++ b/hw/xquartz/X11Application.h @@ -81,6 +81,7 @@ extern int quartzHasRoot, quartzEnableRootless; #define PREFS_FAKEBUTTONS "enable_fake_buttons" #define PREFS_SYSBEEP "enable_system_beep" #define PREFS_KEYEQUIVS "enable_key_equivalents" +#define PREFS_FULLSCREEN_HOTKEYS "fullscreen_hotkeys" #define PREFS_SYNC_KEYMAP "sync_keymap" #define PREFS_DEPTH "depth" #define PREFS_NO_AUTH "no_auth" diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index f120af034..2d3fa7cc9 100644 --- a/hw/xquartz/X11Application.m +++ b/hw/xquartz/X11Application.m @@ -625,16 +625,12 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP default:quartzUseSysBeep]; - - // TODO: Add fullscreen support - //quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS - // default:quartzEnableRootless]; -#ifdef DARWIN_DDX_MISSING +#if 0 + quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS + default:quartzEnableRootless]; quartzFullscreenDisableHotkeys = ![self prefs_get_boolean: @PREFS_FULLSCREEN_HOTKEYS default: !quartzFullscreenDisableHotkeys]; - quartzXpluginOptions = [self prefs_get_integer:@PREFS_XP_OPTIONS - default:quartzXpluginOptions]; #endif darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS default:darwinFakeButtons]; diff --git a/hw/xquartz/X11Controller.m b/hw/xquartz/X11Controller.m index 2482c05f6..85133868b 100644 --- a/hw/xquartz/X11Controller.m +++ b/hw/xquartz/X11Controller.m @@ -595,10 +595,8 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row - (IBAction) enable_fullscreen_changed:sender { int value = ![enable_fullscreen intValue]; - -#ifdef DARWIN_DDX_MISSING + DarwinSendDDXEvent(kXquartzSetRootless, 1, value); -#endif [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:value]; [NSApp prefs_synchronize]; @@ -606,9 +604,7 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row - (IBAction) toggle_fullscreen:sender { -#ifdef DARWIN_DDX_MISSING DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); -#endif } - (void) set_can_quit:(OSX_BOOL)state diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index c31dffd48..89e73c47a 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -231,27 +231,20 @@ static void DarwinEventHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, in case kXquartzToggleFullscreen: DEBUG_LOG("kXquartzToggleFullscreen\n"); -#ifdef DARWIN_DDX_MISSING if (quartzEnableRootless) QuartzSetFullscreen(!quartzHasRoot); else if (quartzHasRoot) QuartzHide(); else - QuartzShow(); -#else - // ErrorF("kXquartzToggleFullscreen not implemented\n"); -#endif + QuartzShow(xe[i].u.keyButtonPointer.rootX, + xe[i].u.keyButtonPointer.rootY); break; case kXquartzSetRootless: DEBUG_LOG("kXquartzSetRootless\n"); -#ifdef DARWIN_DDX_MISSING QuartzSetRootless(xe[i].u.clientMessage.u.l.longs0); if (!quartzEnableRootless && !quartzHasRoot) QuartzHide(); -#else - // ErrorF("kXquartzSetRootless not implemented\n"); -#endif break; case kXquartzSetRootClip: diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c index 616c2b01e..6d1846bec 100644 --- a/hw/xquartz/quartz.c +++ b/hw/xquartz/quartz.c @@ -61,6 +61,9 @@ #include #include +#include +#include + #define FAKE_RANDR 1 // Shared global variables for Quartz modes @@ -76,6 +79,7 @@ DevPrivateKey quartzScreenKey = &quartzScreenKeyIndex; int aquaMenuBarHeight = 0; QuartzModeProcsPtr quartzProcs = NULL; const char *quartzOpenGLBundle = NULL; +int quartzFullscreenDisableHotkeys = TRUE; #if defined(RANDR) && !defined(FAKE_RANDR) Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { @@ -228,33 +232,27 @@ RREditConnectionInfo (ScreenPtr pScreen) } #endif -/* - * QuartzDisplayChangeHandler - * Adjust for screen arrangement changes. - */ -void QuartzDisplayChangedHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents) -{ +static void QuartzUpdateScreens(void) { ScreenPtr pScreen; WindowPtr pRoot; int x, y, width, height, sx, sy; xEvent e; - - DEBUG_LOG("QuartzDisplayChangedHandler(): noPseudoramiXExtension=%d, screenInfo.numScreens=%d\n", noPseudoramiXExtension, screenInfo.numScreens); + if (noPseudoramiXExtension || screenInfo.numScreens != 1) { /* FIXME: if not using Xinerama, we have multiple screens, and - to do this properly may need to add or remove screens. Which - isn't possible. So don't do anything. Another reason why - we default to running with Xinerama. */ - + to do this properly may need to add or remove screens. Which + isn't possible. So don't do anything. Another reason why + we default to running with Xinerama. */ + return; } - + pScreen = screenInfo.screens[0]; - + PseudoramiXResetScreens(); quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height); - + dixScreenOrigins[pScreen->myNum].x = x; dixScreenOrigins[pScreen->myNum].y = y; pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); @@ -266,21 +264,20 @@ void QuartzDisplayChangedHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, if(!QuartzRandRInit(pScreen)) FatalError("Failed to init RandR extension.\n"); #endif - + DarwinAdjustScreenOrigins(&screenInfo); quartzProcs->UpdateScreen(pScreen); - + sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX; sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY; - + /* Adjust the root window. */ pRoot = WindowTable[pScreen->myNum]; AppleWMSetScreenOrigin(pRoot); pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); -// QuartzIgnoreNextWarpCursor(); DefineInitialRootWindow(pRoot); - + /* Send an event for the root reconfigure */ e.u.u.type = ConfigureNotify; e.u.configureNotify.window = pRoot->drawable.id; @@ -292,12 +289,71 @@ void QuartzDisplayChangedHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, e.u.configureNotify.borderWidth = wBorderWidth(pRoot); e.u.configureNotify.override = pRoot->overrideRedirect; DeliverEvents(pRoot, &e, 1, NullWindow); - + #ifdef FAKE_RANDR RREditConnectionInfo(pScreen); -#endif +#endif } +/* + * QuartzDisplayChangeHandler + * Adjust for screen arrangement changes. + */ +void QuartzDisplayChangedHandler(int screenNum, xEventPtr xe, DeviceIntPtr dev, int nevents) { + QuartzUpdateScreens(); +} + +void QuartzSetFullscreen(Bool state) { + if(quartzHasRoot == state) + return; + + quartzHasRoot = state; + + xp_disable_update (); + + if (!quartzHasRoot && !quartzEnableRootless) + RootlessHideAllWindows(); + + RootlessUpdateRooted(quartzHasRoot); + + if (quartzHasRoot && !quartzEnableRootless) + RootlessShowAllWindows (); + + /* Only update screen info when something is visible. Avoids the wm + * moving the windows out from under the menubar when it shouldn't + */ + if (quartzHasRoot || quartzEnableRootless) + QuartzUpdateScreens(); + + /* Somehow the menubar manages to interfere with our event stream + * in fullscreen mode, even though it's not visible. + */ + + X11ApplicationShowHideMenubar(!quartzHasRoot); + + xp_reenable_update (); + + if (quartzFullscreenDisableHotkeys) + xp_disable_hot_keys(quartzHasRoot); +} + +void QuartzSetRootless(Bool state) { + if(quartzEnableRootless == state) + return; + + quartzEnableRootless = state; + + if (!quartzEnableRootless && !quartzHasRoot) { + xp_disable_update(); + RootlessHideAllWindows(); + xp_reenable_update(); + } else if (quartzEnableRootless && !quartzHasRoot) { + xp_disable_update(); + RootlessShowAllWindows(); + QuartzUpdateScreens(); + xp_reenable_update(); + } +} /* * QuartzShow @@ -311,14 +367,18 @@ void QuartzShow( { int i; - if (!quartzServerVisible) { - quartzServerVisible = TRUE; - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - quartzProcs->ResumeScreen(screenInfo.screens[i], x, y); - } + if (quartzServerVisible) + return; + + quartzServerVisible = TRUE; + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + quartzProcs->ResumeScreen(screenInfo.screens[i], x, y); } } + + if (!quartzEnableRootless) + QuartzSetFullscreen(TRUE); } @@ -339,6 +399,8 @@ void QuartzHide(void) } } } + + QuartzSetFullscreen(FALSE); quartzServerVisible = FALSE; } diff --git a/hw/xquartz/quartz.h b/hw/xquartz/quartz.h index 1b6d71f20..8b04b798e 100644 --- a/hw/xquartz/quartz.h +++ b/hw/xquartz/quartz.h @@ -137,4 +137,7 @@ void QuartzShow(int x, int y); // (x, y) = cursor loc void QuartzHide(void); void QuartzSetRootClip(BOOL enable); void QuartzSpaceChanged(uint32_t space_id); + +void QuartzSetFullscreen(Bool state); +void QuartzSetRootless(Bool state); #endif diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h index e63c2b760..a17ebb24e 100644 --- a/hw/xquartz/quartzCommon.h +++ b/hw/xquartz/quartzCommon.h @@ -60,6 +60,7 @@ extern int quartzUseSysBeep; extern int focusOnNewWindow; extern int quartzUseAGL; extern int quartzEnableKeyEquivalents; +extern int quartzFullscreenDisableHotkeys; // Other shared data extern int quartzServerVisible; diff --git a/miext/rootless/rootlessCommon.h b/miext/rootless/rootlessCommon.h index 3d338910f..034d563c6 100644 --- a/miext/rootless/rootlessCommon.h +++ b/miext/rootless/rootlessCommon.h @@ -273,7 +273,8 @@ Bool RootlessResolveColormap (ScreenPtr pScreen, int first_color, void RootlessFlushWindowColormap (WindowPtr pWin); void RootlessFlushScreenColormaps (ScreenPtr pScreen); -RootlessColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors); +// xp_error +int RootlessColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors); // Move a window to its proper location on the screen. void RootlessRepositionWindow(WindowPtr pWin); @@ -281,4 +282,13 @@ void RootlessRepositionWindow(WindowPtr pWin); // Move the window to it's correct place in the physical stacking order. void RootlessReorderWindow(WindowPtr pWin); +void RootlessScreenExpose (ScreenPtr pScreen); +void RootlessHideAllWindows (void); +void RootlessShowAllWindows (void); +void RootlessUpdateRooted (Bool state); + +void RootlessEnableRoot (ScreenPtr pScreen); +void RootlessDisableRoot (ScreenPtr pScreen); + + #endif /* _ROOTLESSCOMMON_H */ diff --git a/miext/rootless/rootlessScreen.c b/miext/rootless/rootlessScreen.c index 421c03c00..0db51d55a 100644 --- a/miext/rootless/rootlessScreen.c +++ b/miext/rootless/rootlessScreen.c @@ -475,6 +475,34 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, return result; } +expose_1 (WindowPtr pWin) +{ + WindowPtr pChild; + + if (!pWin->realized) + return; + + (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, &pWin->borderClip, + PW_BACKGROUND); + + /* FIXME: comments in windowstr.h indicate that borderClip doesn't + include subwindow visibility. But I'm not so sure.. so we may + be exposing too much.. */ + + miSendExposures (pWin, &pWin->borderClip, + pWin->drawable.x, pWin->drawable.y); + + for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) + expose_1 (pChild); +} + +void +RootlessScreenExpose (ScreenPtr pScreen) +{ + expose_1 (WindowTable[pScreen->myNum]); +} + + ColormapPtr RootlessGetColormap (ScreenPtr pScreen) { @@ -718,3 +746,18 @@ Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) return TRUE; } + +void RootlessUpdateRooted (Bool state) { + int i; + + if (!state) + { + for (i = 0; i < screenInfo.numScreens; i++) + RootlessDisableRoot (screenInfo.screens[i]); + } + else + { + for (i = 0; i < screenInfo.numScreens; i++) + RootlessEnableRoot (screenInfo.screens[i]); + } +} diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c index c0554f4de..5ef139101 100644 --- a/miext/rootless/rootlessWindow.c +++ b/miext/rootless/rootlessWindow.c @@ -1581,3 +1581,105 @@ RootlessOrderAllWindows (void) } RL_DEBUG_MSG("RootlessOrderAllWindows() done"); } + +void +RootlessEnableRoot (ScreenPtr pScreen) +{ + WindowPtr pRoot; + pRoot = WindowTable[pScreen->myNum]; + + RootlessEnsureFrame (pRoot); + (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); + RootlessReorderWindow (pRoot); +} + +void +RootlessDisableRoot (ScreenPtr pScreen) +{ + WindowPtr pRoot; + RootlessWindowRec *winRec; + + pRoot = WindowTable[pScreen->myNum]; + winRec = WINREC (pRoot); + + if (winRec != NULL) + { + RootlessDestroyFrame (pRoot, winRec); + DeleteProperty (pRoot, xa_native_window_id ()); + } +} + +void +RootlessHideAllWindows (void) +{ + int i; + ScreenPtr pScreen; + WindowPtr pWin; + RootlessWindowRec *winRec; + xp_window_changes wc; + + if (windows_hidden) + return; + + windows_hidden = TRUE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pWin = WindowTable[i]; + if (pScreen == NULL || pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) + { + if (!pWin->realized) + continue; + + RootlessStopDrawing (pWin, FALSE); + + winRec = WINREC (pWin); + if (winRec != NULL) + { + wc.stack_mode = XP_UNMAPPED; + wc.sibling = 0; + configure_window ((xp_window_id)winRec->wid, XP_STACKING, &wc); + } + } + } +} + +void +RootlessShowAllWindows (void) +{ + int i; + ScreenPtr pScreen; + WindowPtr pWin; + RootlessWindowRec *winRec; + + if (!windows_hidden) + return; + + windows_hidden = FALSE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pWin = WindowTable[i]; + if (pScreen == NULL || pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) + { + if (!pWin->realized) + continue; + + winRec = RootlessEnsureFrame (pWin); + if (winRec == NULL) + continue; + + RootlessReorderWindow (pWin); + } + + RootlessScreenExpose (pScreen); + } +}