Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Copyright (C) 1998 by Jorrit Tyberghein
- Copyright (C) 2001 by Samuel Humphreys
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <stdarg.h>
- #include "cssysdef.h"
- #include "csutil/sysfunc.h"
- #include "csutil/scf.h"
- #include "ivaria/reporter.h"
- #include "csgeom/csrect.h"
- #include "csutil/cfgacc.h"
- #include "xextf86vm.h"
- //#include "xextxrandr.h"
- SCF_IMPLEMENT_FACTORY (csXExtF86VM)
- csXExtF86VM::csXExtF86VM (iBase* parent)
- : scfImplementationType (this, parent)
- {
- dpy = 0;
- screen_num = 0;
- width = height = 0;
- fs_win = wm_win = ctx_win = 0;
- }
- csXExtF86VM::~csXExtF86VM ()
- {
- }
- //=========================================================
- // C H E C K F U L L S C R E E N S E T T I N G
- //=========================================================
- bool csXExtF86VM::Initialize (iObjectRegistry *object_reg)
- {
- this->object_reg = object_reg;
- csConfigAccess Config(object_reg, "/config/video.cfg");
- full_screen = Config->GetBool ("Video.FullScreen", false);
- return true;
- }
- //=========================================================
- // E R R O R R E P O R T I N G
- //=========================================================
- void csXExtF86VM::Report (int severity, const char* msg, ...)
- {
- va_list arg;
- va_start (arg, msg);
- csRef<iReporter> rep (csQueryRegistry<iReporter> (object_reg));
- if (rep)
- rep->ReportV (severity, "crystalspace.window.x.extf86vm", msg, arg);
- else
- {
- csPrintfV (msg, arg);
- csPrintf ("\n");
- }
- va_end (arg);
- }
- //=========================================================
- // O P E N D I S P L A Y
- //=========================================================
- bool csXExtF86VM::Open (Display *dpy, int screen_num,
- XVisualInfo *xvis, Colormap cmap)
- {
- if (!ctx_win || !wm_win)
- {
- Report (CS_REPORTER_SEVERITY_ERROR, "No Windows Set\n");
- return false;
- }
- this->dpy = dpy;
- this->screen_num = screen_num;
- unsigned long cw_fs_mask = (CWOverrideRedirect |
- CWBorderPixel |
- (cmap ? CWColormap : 0));
- XSetWindowAttributes swa;
- memset (&swa, 0, sizeof(swa));
- swa.colormap = cmap;
- swa.override_redirect = True;
- swa.background_pixel = 0;
- swa.border_pixel = 0;
- swa.event_mask = 0;
- fs_win = XCreateWindow (dpy,
- RootWindow (dpy, screen_num),
- 0, 0, 1, 1,
- 0,
- xvis->depth,
- InputOutput,
- xvis->visual,
- cw_fs_mask,
- &swa);
- XStoreName (dpy, fs_win, "Full Screen");
- XSetWindowBackground (dpy, fs_win, BlackPixel (dpy, screen_num));
- XSelectInput (dpy, fs_win, 0);
- if (full_screen)
- {
- full_screen = false;
- EnterFullScreen ();
- return full_screen;
- }
- return true;
- }
- //=========================================================
- // C L O S E D I S P L A Y
- //=========================================================
- void csXExtF86VM::Close ()
- {
- ctx_win = wm_win = 0;
- if (full_screen)
- LeaveFullScreen ();
- XDestroyWindow (dpy, fs_win);
- fs_win = 0;
- }
- //=========================================================
- // S E T F U L L S C R E E N
- //=========================================================
- bool csXExtF86VM::SetFullScreen (bool yesno)
- {
- if (!ctx_win)
- {
- // In initialization phase and configuring
- full_screen = yesno;
- return false;
- }
- if (full_screen != yesno)
- {
- if (yesno)
- EnterFullScreen ();
- else
- LeaveFullScreen ();
- return (full_screen == yesno);
- }
- return false;
- }
- //-----------------------------------------------------------------------------
- #ifndef HAVE_XRANDR // X F 8 6 V M
- //-----------------------------------------------------------------------------
- //=========================================================
- // X F 8 6 V M G E T R E S O L U T I O N I N F O
- //=========================================================
- static bool GetModeInfo (Display *dpy, int scr, XF86VidModeModeInfo *info)
- {
- XF86VidModeModeLine *l;
- l = (XF86VidModeModeLine *) ((char *)info + sizeof(info->dotclock));
- return XF86VidModeGetModeLine (dpy, scr, (int *)&info->dotclock, l);
- }
- //=========================================================
- // X F 8 6 V M C H A N G E M O D E S
- //=========================================================
- void csXExtF86VM::ChangeVideoMode (int zoom)
- {
- XF86VidModeLockModeSwitch (dpy, screen_num, false);
- if (XF86VidModeSwitchMode (dpy, screen_num, zoom))
- {
- if (!GetModeInfo (dpy, screen_num, &fs_mode))
- Report (CS_REPORTER_SEVERITY_ERROR, "Unable to retrieve mode info ");
- width = fs_mode.hdisplay;
- height = fs_mode.vdisplay;
- XResizeWindow (dpy, fs_win, fs_mode.hdisplay, fs_mode.vdisplay);
- XF86VidModeSetViewPort(dpy, screen_num, 0, 0);
- Report (CS_REPORTER_SEVERITY_NOTIFY, "%s VIDEOMODE: %d, %d\n",
- zoom == -1 ? "UP" : "DOWN",
- width, height);
- }
- XF86VidModeLockModeSwitch (dpy, screen_num, true);
- }
- //=========================================================
- // X F 8 6 V M C O M P A R E M O D E S
- //=========================================================
- static int cmp_modes (const void *va, const void *vb)
- {
- XF86VidModeModeInfo *a = *(XF86VidModeModeInfo **) va;
- XF86VidModeModeInfo *b = *(XF86VidModeModeInfo **) vb;
- if (a->hdisplay > b->hdisplay)
- return -1;
- else
- return b->vdisplay - a->vdisplay;
- }
- //=========================================================
- // X F 8 6 V M F I N D B E S T M O D E
- //=========================================================
- void csXExtF86VM::FindBestMode (int ctx_width, int ctx_height)
- {
- XF86VidModeModeLine mode;
- XF86VidModeModeInfo **modes;
- int i, nModes, best_mode = 0;
- bool valid = false;
- unsigned int diff;
- unsigned int best_diff = (unsigned int) -1;
- if (XF86VidModeGetModeLine(dpy, screen_num, &i, &mode)
- && XF86VidModeGetAllModeLines (dpy, screen_num, &nModes, &modes))
- {
- qsort (modes, nModes, sizeof (*modes), cmp_modes);
- // find best full screen mode
- for (i = nModes - 1; i >= 0; --i)
- {
- if (modes[i]->hdisplay >= ctx_width && modes[i]->vdisplay >= ctx_height)
- {
- fs_mode = *modes[i];
- valid = true;
- break;
- }
- diff = ctx_width - modes[i]->hdisplay;
- if (diff < best_diff)
- best_mode = i;
- }
- if (!valid)
- fs_mode = *modes[best_mode];
- XFree (modes);
- }
- }
- //=========================================================
- // X F 8 6 V M S W I T C H M O D E
- //=========================================================
- bool csXExtF86VM::SwitchMode (XF86VidModeModeInfo *to_mode,
- XF86VidModeModeInfo *from_mode,
- bool lock, int vp_x, int vp_y)
- {
- XF86VidModeLockModeSwitch (dpy, screen_num, lock);
- if (to_mode->hdisplay != from_mode->hdisplay ||
- to_mode->vdisplay != from_mode->vdisplay)
- {
- if (!XF86VidModeSwitchToMode (dpy, screen_num, to_mode))
- {
- Report (CS_REPORTER_SEVERITY_ERROR, "Unable to restore mode %hux%hu",
- to_mode->hdisplay, to_mode->vdisplay);
- return false;
- }
- }
- XF86VidModeSetViewPort(dpy, screen_num, vp_x, vp_y);
- return true;
- }
- //-----------------------------------------------------------------------------
- #else // X R A N D R
- //-----------------------------------------------------------------------------
- //=========================================================
- // X R A N D R G E T R E S O L U T I O N I N F O
- //=========================================================
- static bool GetResInfo (Display *dpy, int scr, XRANDR_SCRN_CFG *info)
- {
- XRRScreenConfiguration *sc;
- XRRScreenSize *size_list;
- int num_sizes, temp_idx;
- Rotation current_rotation;
- sc = XRRGetScreenInfo(dpy, RootWindow (dpy, scr));
- if (sc)
- {
- temp_idx = XRRConfigCurrentConfiguration (sc, ¤t_rotation);
- size_list = XRRConfigSizes( sc, &num_sizes );
- info->res_idx = temp_idx;
- info->rotation = current_rotation;
- info->width = size_list[temp_idx].width;
- info->height = size_list[temp_idx].height;
- info->num_sizes = num_sizes;
- XRRFreeScreenConfigInfo(sc);
- return true;
- }
- return false;
- }
- //=========================================================
- // X R A N D R C H A N G E R E S O L U T I O N S
- //=========================================================
- /*
- I used xvidtune to help guess which way "zoom" was supposed to work
- so hopefully I got it right
- way more code than the xf86vm version, but if it works who cares
- */
- void csXExtF86VM::ChangeVideoRes (int zoom)
- {
- XRANDR_SCRN_CFG current_scrn_info;
- XRRScreenConfiguration *sc;
- int res_index;
- bool valid;
- sc = XRRGetScreenInfo(dpy, RootWindow (dpy, screen_num));
- if (GetResInfo (dpy, screen_num, ¤t_scrn_info)) // if valid info
- {
- // going to smaller resolution
- if (zoom > 0)
- {
- res_index = current_scrn_info.res_idx +1;
- csPrintf ("going to smaller resolution\n");
- if (current_scrn_info.res_idx +1 > current_scrn_info.num_sizes)
- {
- valid = true;
- }
- }
- // going to larger resolution
- else
- {
- res_index = current_scrn_info.res_idx -1;
- csPrintf ("going to larger resolution\n");
- if (current_scrn_info.res_idx > 0)
- {
- valid = true;
- }
- }
- if (valid)
- {
- XRRSetScreenConfig(dpy, sc, RootWindow (dpy, screen_num),
- res_index,current_scrn_info.rotation,
- CurrentTime);
- width = current_scrn_info.width;
- height = current_scrn_info.height;
- XResizeWindow (dpy, fs_win, fs_scn_cfg.width, fs_scn_cfg.height);
- Report (CS_REPORTER_SEVERITY_NOTIFY, "%s VIDEOMODE: %d, %d\n",
- zoom == -1 ? "UP" : "DOWN",
- width, height);
- }
- }
- else
- Report (CS_REPORTER_SEVERITY_ERROR, "Unable to retrieve mode info ");
- XRRFreeScreenConfigInfo(sc);
- }
- //=========================================================
- // X R A N D R F I N D B E S T R E S O L U T I O N
- //=========================================================
- /*
- Unlike XF86VM extensions, the XRANDR extensions use an index value to set
- the screen size
- */
- void csXExtF86VM::FindBestRes (int ctx_width, int ctx_height)
- {
- // common variables
- bool valid = false;
- unsigned int diff;
- unsigned int best_diff = (unsigned int) -1;
- // XRANDR variables
- int j, current_index, num_sizes, best_size_idx = 0;
- Rotation current_rotation;
- XRRScreenConfiguration *sc;
- XRRScreenSize *size_list;
- sc = XRRGetScreenInfo(dpy, RootWindow (dpy, screen_num));
- size_list = XRRConfigSizes( sc, &num_sizes );
- // just looking for the rotation
- current_index = XRRConfigCurrentConfiguration (sc, ¤t_rotation);
- csPrintf ("Testing XRANDR code:\n");
- csPrintf ("looking at sizes on screen: %d\n", screen_num);
- // find best full screen mode
- for (j = num_sizes - 1; j >= 0; --j)
- {
- csPrintf ("size_list[%d].width: %hu Number of display pixels horizontally\n", j, size_list[j].width);
- csPrintf ("size_list[%d].height: %hu Number of display pixels vertically\n\n", j, size_list[j].height);
- if ((size_list[j].width >= ctx_width) && (size_list[j].height >= ctx_height))
- {
- best_size_idx = j;
- valid = true;
- break;
- }
- diff = ctx_width - size_list[j].width;
- if (diff < best_diff)
- best_size_idx = j;
- }
- if (!valid)
- {
- csPrintf ("No valid screen resolution match found!\n");
- best_size_idx = 0;
- }
- fs_scn_cfg.width = size_list[best_size_idx].width;
- fs_scn_cfg.height = size_list[best_size_idx].height;
- fs_scn_cfg.res_idx = best_size_idx;
- fs_scn_cfg.rotation = current_rotation;
- fs_scn_cfg.num_sizes = num_sizes;
- XRRFreeScreenConfigInfo(sc);
- csPrintf ("XRANDR chose %hux%hu as best resolution.\n",
- size_list[best_size_idx].width, size_list[best_size_idx].height);
- }
- //=========================================================
- // X R A N D R S W I T C H R E S O L U T I O N
- //=========================================================
- bool csXExtF86VM::SwitchRes ( XRANDR_SCRN_CFG *to_mode,
- XRANDR_SCRN_CFG *from_mode)
- {
- // XRANDR variables
- Rotation current_rotation;
- XRRScreenConfiguration *sc;
- int test1, major_version, minor_version;
- test1 = XRRQueryVersion (dpy, &major_version, &minor_version);
- csPrintf ("test1 %hu, major version:%d, minor version %d\n\n",
- test1, major_version, minor_version);
- csPrintf ("Attempting to switch resolution on screen_num: %d\n", screen_num);
- csPrintf ("to_mode->width: %hu\n", to_mode->width);
- csPrintf ("to_mode->height: %hu\n", to_mode->height);
- csPrintf ("to_mode->rotation: %hu\n", to_mode->rotation);
- csPrintf ("to_mode->res_idx: %hu\n", to_mode->res_idx);
- csPrintf ("to_mode->num_sizes: %hu\n\n", to_mode->num_sizes);
- csPrintf ("From resolution:\n");
- csPrintf ("from_mode->width: %hu\n", from_mode->width);
- csPrintf ("from_mode->height: %hu\n", from_mode->height);
- csPrintf ("from_mode->rotation: %hu\n", from_mode->rotation);
- csPrintf ("from_mode->res_idx: %hu\n", from_mode->res_idx);
- csPrintf ("from_mode->num_sizes: %hu\n\n", from_mode->num_sizes);
- sc = XRRGetScreenInfo(dpy, RootWindow (dpy, screen_num));
- if (sc)
- {
- if (to_mode->width != from_mode->width ||
- to_mode->height != from_mode->height)
- {
- int status = (XRRSetScreenConfig(dpy, sc, RootWindow (dpy, screen_num),
- to_mode->res_idx,to_mode->rotation,
- CurrentTime));
- csPrintf ("Result:\n");
- switch (status)
- {
- case RRSetConfigSuccess:
- csPrintf ("RRSetConfigSuccess\n");
- break;
- case GrabNotViewable:
- csPrintf ("RRSetConfigInvalidConfigTime\n");
- break;
- case GrabFrozen:
- csPrintf ("RRSetConfigInvalidTime\n");
- break;
- case GrabInvalidTime:
- csPrintf ("RRSetConfigFailed\n");
- break;
- default :
- csPrintf ("Unknown error\n");
- break;
- }
- // return of 0 indicates successful change, anything else is error value
- if (status != RRSetConfigSuccess)
- {
- Report (CS_REPORTER_SEVERITY_ERROR, "Unable to restore mode %hux%hu",
- to_mode->width, to_mode->height);
- return false;
- }
- }
- XRRFreeScreenConfigInfo(sc);
- sleep(3);
- return true;
- }
- return false;
- }
- #endif
- //=========================================================
- // E N T E R F U L L S C R E E N
- //=========================================================
- void csXExtF86VM::EnterFullScreen ()
- {
- XWindowAttributes wa;
- // only switch if needed
- if (full_screen)
- return;
- if (!XGetWindowAttributes (dpy, ctx_win, &wa))
- return;
- #ifndef HAVE_XRANDR
- FindBestMode (wa.width, wa.height);
- #ifdef CS_DEBUG
- csPrintf ("Entering fullscreen: win %d, %d to fs_mode %hu, %hu\n\n",
- wa.width, wa.height, fs_mode.hdisplay, fs_mode.vdisplay);
- #endif
- XResizeWindow (dpy, fs_win, fs_mode.hdisplay, fs_mode.vdisplay);
- #else
- FindBestRes (wa.width, wa.height);
- #ifdef CS_DEBUG
- csPrintf ("Entering fullscreen: win %d, %d to fs_mode %hu, %hu\n\n",
- wa.width, wa.height, fs_scn_cfg.width, fs_scn_cfg.height);
- #endif
- XResizeWindow (dpy, fs_win, fs_scn_cfg.width, fs_scn_cfg.height);
- #endif
- XClearWindow (dpy, fs_win);
- XMapRaised (dpy, fs_win);
- #ifndef HAVE_XRANDR
- //-xf86vm
- // save current display information
- GetModeInfo (dpy, screen_num, &wm_mode);
- XF86VidModeGetViewPort (dpy, screen_num, &viewport_x, &viewport_y);
- #else
- //-xrandr
- // save current display information
- GetResInfo (dpy, screen_num , &wm_scn_cfg);
- // no viewport info for xrandr
- #endif
- int test1 = XGrabPointer (dpy, fs_win, True, 0, GrabModeAsync, GrabModeAsync, fs_win, None, CurrentTime);
- int test2 = XGrabKeyboard (dpy, fs_win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- csPrintf ("XGrabPointer: ");
- switch( test1 )
- {
- case AlreadyGrabbed:
- csPrintf ("AlreadyGrabbed\n");
- break;
- case GrabNotViewable:
- csPrintf ("GrabNotViewable\n");
- break;
- case GrabFrozen:
- csPrintf ("GrabFrozen\n");
- break;
- case GrabInvalidTime:
- csPrintf ("XGrGrabInvalidTime\n");
- break;
- case GrabSuccess:
- csPrintf ("GrabSuccess\n");
- break;
- default :
- csPrintf ("Unknown error\n");
- break;
- }
- csPrintf ("XGrabKeyboard: ");
- switch( test2 )
- {
- case AlreadyGrabbed:
- csPrintf ("AlreadyGrabbed\n");
- break;
- case GrabNotViewable:
- csPrintf ("GrabNotViewable\n");
- break;
- case GrabFrozen:
- csPrintf ("GrabFrozen\n");
- break;
- case GrabInvalidTime:
- csPrintf ("GrabInvalidTime\n");
- break;
- case GrabSuccess:
- csPrintf ("GrabSuccess\n");
- break;
- default :
- csPrintf ("Unknown error\n");
- break;
- }
- #ifndef HAVE_XRANDR
- bool test3 = SwitchMode (&fs_mode, &wm_mode, true, 0, 0);
- csPrintf ("SwitchMode: %d\n\n", test3);
- #else
- bool test3 = SwitchRes (&fs_scn_cfg, &wm_scn_cfg);
- csPrintf ("SwitchRes: %d\n\n", test3);
- #endif
- /*
- // grab pointer and keyboard in fullscreen mode
- if ((XGrabPointer (dpy, fs_win, True,
- 0, GrabModeAsync, GrabModeAsync,
- fs_win, None, CurrentTime) == GrabSuccess) &&
- //(XGrabKeyboard (dpy, wm_win, True, GrabModeAsync,
- (XGrabKeyboard (dpy, fs_win, True, GrabModeAsync,
- GrabModeAsync, CurrentTime) == GrabSuccess) &&
- #ifndef HAVE_XRANDR
- //xf86vm
- SwitchMode (&fs_mode, &wm_mode, true, 0, 0))
- #else
- // xrandr
- SwitchRes (&fs_scn_cfg, &wm_scn_cfg))
- #endif
- */
- if ((test1 == GrabSuccess) && (test2 == GrabSuccess) && test3)
- {
- full_screen = true;
- XReparentWindow (dpy, ctx_win, fs_win, 0, 0);
- XWarpPointer (dpy, None, ctx_win,
- 0, 0, 0, 0,
- #ifndef HAVE_XRANDR
- fs_mode.hdisplay >> 1,
- fs_mode.vdisplay >> 1);
- width = fs_mode.hdisplay;
- height = fs_mode.vdisplay;
- #else
- fs_scn_cfg.width >> 1,
- fs_scn_cfg.height >> 1);
- width = fs_scn_cfg.width;
- height = fs_scn_cfg.height;
- #endif
- Report (CS_REPORTER_SEVERITY_NOTIFY, "FULL SCREEN: %d, %d", width, height);
- XSync (dpy, False);
- }
- else
- {
- XUnmapWindow (dpy, fs_win);
- Report (CS_REPORTER_SEVERITY_ERROR, "Unable to switch mode");
- }
- }
- //=========================================================
- // L E A V E F U L L S C R E E N
- //=========================================================
- /*
- Work in progress
- */
- void csXExtF86VM::LeaveFullScreen ()
- {
- XWindowAttributes wa;
- #ifndef HAVE_XRANDR
- XF86VidModeModeInfo mode;
- if (!full_screen)
- return;
- GetModeInfo (dpy, screen_num, &mode);
- bool ret = SwitchMode (&wm_mode, &fs_mode, false, viewport_x, viewport_y);
- #else
- XRANDR_SCRN_CFG res_info;
- if (!full_screen)
- return;
- GetResInfo (dpy, screen_num, &res_info);
- bool ret = SwitchRes(&wm_scn_cfg, &fs_scn_cfg);
- #endif
- XUngrabPointer (dpy, CurrentTime);
- XUngrabKeyboard (dpy, CurrentTime);
- if (!ret)
- {
- Report (CS_REPORTER_SEVERITY_ERROR,
- "Unable to return to windowed mode....aborting\n");
- exit (-1);
- }
- if (wm_win != 0)
- {
- if (!XGetWindowAttributes (dpy, wm_win, &wa))
- return;
- XReparentWindow (dpy, ctx_win, wm_win, 0, 0);
- width = wa.width;
- height = wa.height;
- XWarpPointer (dpy, None, ctx_win,
- 0, 0, 0, 0,
- wa.width >> 1,
- wa.height >> 1);
- }
- full_screen = false;
- XUnmapWindow (dpy, fs_win);
- XSync (dpy, False);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement