dosemu-devel Mailing List for DOSEMU for Linux
                
                Brought to you by:
                
                    bartoldeman
                    
                
            
            
        
        
        
    You can subscribe to this list here.
| 2002 | Jan | Feb | Mar (4) | Apr (5) | May (17) | Jun (9) | Jul | Aug (4) | Sep (2) | Oct (20) | Nov (16) | Dec (35) | 
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 | Jan (138) | Feb (104) | Mar (20) | Apr (14) | May (26) | Jun (13) | Jul (8) | Aug (20) | Sep (4) | Oct | Nov (21) | Dec | 
| 2004 | Jan (22) | Feb (8) | Mar (17) | Apr (25) | May (12) | Jun (17) | Jul (9) | Aug (1) | Sep (31) | Oct (5) | Nov (20) | Dec (7) | 
| 2005 | Jan | Feb (2) | Mar (11) | Apr (1) | May (1) | Jun | Jul (42) | Aug (13) | Sep (7) | Oct | Nov (31) | Dec (36) | 
| 2006 | Jan (25) | Feb (9) | Mar (37) | Apr (13) | May (11) | Jun (2) | Jul | Aug (9) | Sep | Oct (11) | Nov (13) | Dec | 
| 2007 | Jan (4) | Feb (3) | Mar (3) | Apr (6) | May (6) | Jun | Jul | Aug (2) | Sep (1) | Oct | Nov (5) | Dec | 
| 2008 | Jan | Feb (12) | Mar (1) | Apr (6) | May (9) | Jun | Jul (7) | Aug (3) | Sep | Oct | Nov (3) | Dec (1) | 
| 2009 | Jan (1) | Feb | Mar (1) | Apr (6) | May (11) | Jun (3) | Jul (2) | Aug (10) | Sep (7) | Oct (1) | Nov | Dec | 
| 2010 | Jan (1) | Feb | Mar (2) | Apr (2) | May | Jun | Jul (4) | Aug | Sep | Oct (1) | Nov | Dec | 
| 2011 | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep (8) | Oct (1) | Nov | Dec | 
| 2012 | Jan | Feb | Mar | Apr (48) | May (25) | Jun | Jul | Aug (5) | Sep (1) | Oct (23) | Nov (25) | Dec (22) | 
| 2013 | Jan (37) | Feb (13) | Mar (15) | Apr (4) | May | Jun (48) | Jul (36) | Aug (2) | Sep | Oct | Nov | Dec (1) | 
| 2014 | Jan | Feb | Mar (4) | Apr (20) | May (19) | Jun (18) | Jul | Aug | Sep (9) | Oct | Nov | Dec | 
| 2015 | Jan (7) | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep (3) | Oct | Nov | Dec (11) | 
| 2016 | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct (2) | Nov | Dec | 
| 2017 | Jan | Feb | Mar | Apr | May | Jun (1) | Jul | Aug | Sep | Oct | Nov | Dec | 
| 
      
      
      From: Stas S. <st...@li...> - 2017-06-16 11:29:14
      
     | 
| Hello dosemu users & developers. It looks like dosemu lists are pretty quiet this days, albeit of a bit spamming from linux-kernel development. This is because dosemu1 development have come to an end (AFAIK), and dosemu2 development/discussing all happens within the github platform. There is probably no need in an MLs any more, because the things can be discussed directly in an issues tracker, in a pull-requests tickets, in a comments to patches, etc etc. There are plenty of possibilities that guthub offers. So I invite everyone interested in dosemu2 development to visit our github page: https://github.com/stsp/dosemu2 click the "Watch" button and participate in the discussions that are happening there. | 
| 
      
      
      From: Stas S. <st...@li...> - 2016-10-28 23:52:32
      
     | 
| 29.10.2016 02:26, Linus Torvalds пишет: > On Fri, Oct 28, 2016 at 2:36 PM, Stas Sergeev <st...@li...> wrote: >>>>> On Fri, Oct 28, 2016 at 2:03 PM, Stas Sergeev <st...@li...> wrote: >> Hello. >> >> For the long time dosemu used /dev/mem for vga pass-through. >> Now it appears /dev/mem has this check: >> http://lxr.free-electrons.com/source/drivers/char/mem.c#L51 >> which prevents an accesses to PCI memory regions if the >> "high_memory" points low enough. It seems "high_memory" >> just points to the end of the physical ram, so depending on >> the ram size you either can access PCI devices or you get >> EFAULT. >> Was it wrong to use /dev/mem for accessing the PCI devices? >> How should I do that now? > Has it ever worked for you? Well, yes, even today: if the ram size is large enough to last beyond the PCI space, then I am not getting EFAULT (i've yet to check if the results are as expected, but at least no error returned). It is exactly that ram size envolvement made me think this is a bug (and regression). > That code is ancient, going back in some > form or another at least ten years. Yes, indeed, I can see that on lxr now... > So /dev/mem does not allow "read()/write()" on IO memory, and really > hasn't in a long long time (maybe ever, quite frankly). It does allow > it on regular RAM, but STRICT_DEV_MEM then disallows that too for > security reasons (and realistically, everybody uses STRICT_DEV_MEM > these days). > > What people do use /dev/mem for is to mmap() PCI memory, and then you > can access it from user space. That's the traditional model that X.org > used to do etc. Yes, thanks, I was confused. mmap() is indeed unaffected, only read and write are. So the only problem I have, is the test-case I was trying, that does read/write and works depending on the ram size (under qemu). But there is no any problem for dosemu. Perhaps for consistency it would be good to make things independent of the ram size, but then there is no real problem here. So sorry for the noise! | 
| 
      
      
      From: Stas S. <st...@li...> - 2016-10-28 21:37:03
      
     | 
| OK, thanks for the prompt reply, Andy! I'll try your sysfs suggestion. Let me just add a bit of CCs to get more people involved. I believe the ram size involvement makes this smell like a bug, plus it looks like a regression. Not that I am going to suffer much (this pass-through stuff always breaks in a million of different ways, I'll probably just remove it), but its still a very questionable change IMO. 29.10.2016 00:26, Andy Lutomirski пишет: > On Fri, Oct 28, 2016 at 2:18 PM, Stas Sergeev <st...@li...> wrote: >> 29.10.2016 00:05, Andy Lutomirski пишет: >> >>> On Fri, Oct 28, 2016 at 2:03 PM, Stas Sergeev <st...@li...> wrote: >>>> Hello. >>>> >>>> For the long time dosemu used /dev/mem for vga pass-through. >>>> Now it appears /dev/mem has this check: >>>> http://lxr.free-electrons.com/source/drivers/char/mem.c#L51 >>>> which prevents an accesses to PCI memory regions if the >>>> "high_memory" points low enough. It seems "high_memory" >>>> just points to the end of the physical ram, so depending on >>>> the ram size you either can access PCI devices or you get >>>> EFAULT. >>>> Was it wrong to use /dev/mem for accessing the PCI devices? >>>> How should I do that now? >>>> >>> What is DOSEMU trying to do here? Access the framebuffer? >>> >>> ISTM it would be better to use the DRM or FB layer directly (just map >>> the framebuffer itself) or, if necessary, use VFIO. >> Yes, framebuffer. >> Mapping fb directly is not really an option because dosemu does >> its own modesetting when you do vga pass-through. So it is >> usually started that way with "nomodeset=1" and w/o fb. >> Yes, some crazy people try the pass-through even out of fb >> console, but that's weird (the problem is most SDL2 builds do >> not have directfb backend compiled in, otherwise we could >> just use SDL rendering on top of fb). >> >> The thing is, I needed (for testing purposes, unrelated to dosemu) >> some quick way to access the PCI memory space, and to my surprise I >> couldn't do that with /dev/mem. Was this really disallowed intentionally? > I believe so. > > Try the /sys/devices/.../resource? and resource?_wc files. > > --Andy > | 
| 
      
      
      From: solarflow99 <sol...@gm...> - 2015-12-28 21:57:37
      
     | 
| not since the last 10 years or so On Mon, Dec 28, 2015 at 9:30 AM, Stas Sergeev <st...@li...> wrote: > 24.12.2015 06:06, Bart Oldeman пишет: >> Hello Andreas, >> >> On 22 December 2015 at 07:38, <bo...@ge... <mailto:bo...@ge...>> wrote: >>> Thank you for your reply. I'm on 32-bit and my goal there is to stay >>> with "vm86" for speed. So I don't try to use KVM, even it's installed on >>> this machine. >> >> Just to clarify, there should not be any noticeable speed difference between vm86 and KVM. KVM goes through an extra layer but is also able to use "VME" which means DOS code does not trap as often as >> with plain vm86. > Aren't there the older 32bit CPUs where KVM falls > back to cpu emulation, and is therefore very slow? > > ------------------------------------------------------------------------------ > _______________________________________________ > Dosemu-devel mailing list > Dos...@li... > https://lists.sourceforge.net/lists/listinfo/dosemu-devel | 
| 
      
      
      From: Stas S. <st...@li...> - 2015-12-28 17:31:45
      
     | 
| 24.12.2015 06:06, Bart Oldeman пишет: > Hello Andreas, > > On 22 December 2015 at 07:38, <bo...@ge... <mailto:bo...@ge...>> wrote: >> Thank you for your reply. I'm on 32-bit and my goal there is to stay >> with "vm86" for speed. So I don't try to use KVM, even it's installed on >> this machine. > > Just to clarify, there should not be any noticeable speed difference between vm86 and KVM. KVM goes through an extra layer but is also able to use "VME" which means DOS code does not trap as often as > with plain vm86. Aren't there the older 32bit CPUs where KVM falls back to cpu emulation, and is therefore very slow? | 
| 
      
      
      From: <bo...@ge...> - 2015-12-26 21:42:17
      
     | 
| Hello Bart Thanks for your hint regarding the speed of KVM against VM86. The latest info I found was: https://github.com/stsp/dosemu2/issues/77 If this values are still recent, then it would be OK for some applications. But for productivity or development software under DOS, this difference really matters. Nonetheless, will see to find some time to do a test with KVM too. Andreas On 2015-12-24 04:06, Bart Oldeman wrote: > Hello Andreas, > > On 22 December 2015 at 07:38, <bo...@ge...> wrote: >> Thank you for your reply. I'm on 32-bit and my goal there is to stay >> with "vm86" for speed. So I don't try to use KVM, even it's > installed on >> this machine. > > Just to clarify, there should not be any noticeable speed difference > between vm86 and KVM. KVM goes through an extra layer but is also able > to use "VME" which means DOS code does not trap as often as with plain > vm86. > > Bart | 
| 
      
      
      From: Stas S. <st...@li...> - 2015-12-25 12:24:17
      
     | 
| 25.12.2015 14:02, solarflow99 пишет: > I'd like to update the docs with this info. Any way I can help do that Stas? Sure, please send a pull request. For this, you need to fork the repo (in the web UI) and commit your changes. Then create a pull request. | 
| 
      
      
      From: solarflow99 <sol...@gm...> - 2015-12-25 11:02:16
      
     | 
| I'd like to update the docs with this info. Any way I can help do that Stas? On Wed, Dec 23, 2015 at 7:06 PM, Bart Oldeman <bar...@gm...> wrote: > Hello Andreas, > > On 22 December 2015 at 07:38, <bo...@ge...> wrote: >> Thank you for your reply. I'm on 32-bit and my goal there is to stay >> with "vm86" for speed. So I don't try to use KVM, even it's installed on >> this machine. > > Just to clarify, there should not be any noticeable speed difference between > vm86 and KVM. KVM goes through an extra layer but is also able to use "VME" > which means DOS code does not trap as often as with plain vm86. > > Bart > > ------------------------------------------------------------------------------ > > _______________________________________________ > Dosemu-devel mailing list > Dos...@li... > https://lists.sourceforge.net/lists/listinfo/dosemu-devel > | 
| 
      
      
      From: Bart O. <bar...@gm...> - 2015-12-24 03:06:35
      
     | 
| Hello Andreas, On 22 December 2015 at 07:38, <bo...@ge...> wrote: > Thank you for your reply. I'm on 32-bit and my goal there is to stay > with "vm86" for speed. So I don't try to use KVM, even it's installed on > this machine. Just to clarify, there should not be any noticeable speed difference between vm86 and KVM. KVM goes through an extra layer but is also able to use "VME" which means DOS code does not trap as often as with plain vm86. Bart | 
| 
      
      
      From: <bo...@ge...> - 2015-12-22 12:38:41
      
     | 
| Hello Andrew Thank you for your reply. I'm on 32-bit and my goal there is to stay with "vm86" for speed. So I don't try to use KVM, even it's installed on this machine. My intention was to check first, if that could be a bug or it was by intention. In this case, I will open an issue on github. Andreas On 2015-12-22 12:42, Andrew Bird wrote: > On Tue, 22 Dec 2015 11:34:26 +0100 > bo...@ge... wrote: > >> Hello >> >> I've compiled the DOSEMU2 devel branch (2.0pre4, 1893) on an Ubuntu >> 12.04 LTS (x86 / 32-bit / PAE). This fails due to the usage of >> "X86_EFLAGS_FIXED" in the file "src/emu-i386/kvm.c". >> >> I believe that the define of "X86_EFLAGS_FIXED" is missing in the >> kernel >> 3.2 of my Ubuntu version. There has been a rename of "X86_EFLAGS_BIT1" >> to "X86_EFLAGS_FIXED" some time ago: >> >> https://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.10.60 >> >> >> In the meantime, I added the following line to "kvm.c" and could >> compile >> successfully DOSEMU2: >> >> #define X86_EFLAGS_FIXED 0x00000002 >> >> But I believe, this is NOT the right thing... DOSEMU2 runs, but I use >> "vm86" and not "kvm". >> >> >> So, coming back to the subject of this message: >> >> Is DOSEMU2 supposed to work on older Linux Kernels ? If not, then this >> message can be sent to device null. >> >> Andreas >> >> > > Hi Andreas, > Firstly you should raise an issue at > https://github.com/stsp/dosemu2/issues as it'll get tracked properly > there and Stas / Bart won't miss it. Regarding use of vm86, I think on > 386 kernels it's still the default, so are you forcing it to try kvm? > There's a new dosemu.conf variable called $_cpu_vm since kvm support > got added. Here's the section from the default dosemu.conf. > > # Usage of cpu emulation: "off" (default on x86), > # "vm86" only (default on x86-64) or "full" (vm86 and DPMI, > experimental!). > # Use "vm86sim" or "fullsim" to use simulation instead of JIT code > generation. > > # $_cpu_emu = "off" > > # Select cpu virtualization mode. > # "vm86" - use v86 mode via vm86() syscall. Only available on x86-32. > # "kvm" - use KVM, hardware-assisted in-kernel virtual machine. > # "emulated" - use CPU emulator > # "auto" - select whatever works > > # $_cpu_vm = "auto" > > Remember that kvm support requires a certain processor type to work, > but in any case you should raise the issue because dosemu2 should > definitely compile on kernel 3.2 without changes. | 
| 
      
      
      From: Andrew B. <aj...@sp...> - 2015-12-22 12:07:39
      
     | 
| On Tue, 22 Dec 2015 11:34:26 +0100 bo...@ge... wrote: > Hello > > I've compiled the DOSEMU2 devel branch (2.0pre4, 1893) on an Ubuntu > 12.04 LTS (x86 / 32-bit / PAE). This fails due to the usage of > "X86_EFLAGS_FIXED" in the file "src/emu-i386/kvm.c". > > I believe that the define of "X86_EFLAGS_FIXED" is missing in the kernel > 3.2 of my Ubuntu version. There has been a rename of "X86_EFLAGS_BIT1" > to "X86_EFLAGS_FIXED" some time ago: > > https://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.10.60 > > > In the meantime, I added the following line to "kvm.c" and could compile > successfully DOSEMU2: > > #define X86_EFLAGS_FIXED 0x00000002 > > But I believe, this is NOT the right thing... DOSEMU2 runs, but I use > "vm86" and not "kvm". > > > So, coming back to the subject of this message: > > Is DOSEMU2 supposed to work on older Linux Kernels ? If not, then this > message can be sent to device null. > > Andreas > > Hi Andreas, Firstly you should raise an issue at https://github.com/stsp/dosemu2/issues as it'll get tracked properly there and Stas / Bart won't miss it. Regarding use of vm86, I think on 386 kernels it's still the default, so are you forcing it to try kvm? There's a new dosemu.conf variable called $_cpu_vm since kvm support got added. Here's the section from the default dosemu.conf. # Usage of cpu emulation: "off" (default on x86), # "vm86" only (default on x86-64) or "full" (vm86 and DPMI, experimental!). # Use "vm86sim" or "fullsim" to use simulation instead of JIT code generation. # $_cpu_emu = "off" # Select cpu virtualization mode. # "vm86" - use v86 mode via vm86() syscall. Only available on x86-32. # "kvm" - use KVM, hardware-assisted in-kernel virtual machine. # "emulated" - use CPU emulator # "auto" - select whatever works # $_cpu_vm = "auto" Remember that kvm support requires a certain processor type to work, but in any case you should raise the issue because dosemu2 should definitely compile on kernel 3.2 without changes. -- Andrew Bird <aj...@sp...> | 
| 
      
      
      From: <bo...@ge...> - 2015-12-22 10:34:48
      
     | 
| Hello I've compiled the DOSEMU2 devel branch (2.0pre4, 1893) on an Ubuntu 12.04 LTS (x86 / 32-bit / PAE). This fails due to the usage of "X86_EFLAGS_FIXED" in the file "src/emu-i386/kvm.c". I believe that the define of "X86_EFLAGS_FIXED" is missing in the kernel 3.2 of my Ubuntu version. There has been a rename of "X86_EFLAGS_BIT1" to "X86_EFLAGS_FIXED" some time ago: https://www.kernel.org/pub/linux/kernel/v3.0/ChangeLog-3.10.60 In the meantime, I added the following line to "kvm.c" and could compile successfully DOSEMU2: #define X86_EFLAGS_FIXED 0x00000002 But I believe, this is NOT the right thing... DOSEMU2 runs, but I use "vm86" and not "kvm". So, coming back to the subject of this message: Is DOSEMU2 supposed to work on older Linux Kernels ? If not, then this message can be sent to device null. Andreas | 
| 
      
      
      From: solarflow99 <sol...@gm...> - 2015-12-22 09:10:00
      
     | 
| This is it On Dec 22, 2015 1:09 AM, <bo...@ge...> wrote: > Hello all > > Is this used for discusion about the DOSEMU_2_ too or is there a new one > / other location ? > > Andreas > > > ------------------------------------------------------------------------------ > _______________________________________________ > Dosemu-devel mailing list > Dos...@li... > https://lists.sourceforge.net/lists/listinfo/dosemu-devel > | 
| 
      
      
      From: <bo...@ge...> - 2015-12-22 09:09:02
      
     | 
| Hello all Is this used for discusion about the DOSEMU_2_ too or is there a new one / other location ? Andreas | 
| 
      
      
      From: solarflow99 <sol...@gm...> - 2015-09-16 08:54:03
      
     | 
| I suspect its just a bug with the 64 bit version, some programs, usually games have experienced problems running in 64 bit. On Wed, Sep 16, 2015 at 12:14 AM, Michael D. Setzer II <mi...@ku...> wrote: > On 15 Sep 2015 at 16:51, solarflow99 wrote: > > Date sent: Tue, 15 Sep 2015 16:51:46 -0700 > Subject: Re: [Dosemu-devel] Issue with dosemu after upgrade to > Fedora 22? > From: solarflow99 <sol...@gm...> > To: "Michael D. Setzer II" <mi...@ku...> > Copies to: dosemu-devel <dos...@li...> > >> is this 64 bit? are you using the RPM? >> > > This is the 64bit version on a Lenovo ThinkCenter I7 computer. Was working > with the Fedora 21, but did the fedup update to Fedora 22, and if upgraded to > the Fedora 22 rpm. Changing the $_cpu_emu = "full" seems to have fixed it, > but not sure what changed it no longer work. Could be the upgrade to 22, or > it could just be the new kernels that 22 is not running. Tried the vm option, > but it gave the same error, but changing to full worked. > > Did download and compile the dosemu2, but ran into some issues. Had to > add bison and flex that was no problem, and it compiled and installed, but > when I ran the dosemu, it was coming up with a message about no os found, > and to install freedos. The freedos was already installed, and it was working > with the regular dosemu to load and come up with the c: prompt, just the > running of bc program caused it to get the error. Where the regular dosemu > would show the mapping of the z: to the freedos directory, there was nothing > on that with the dosemu2? > > > >> On Tue, Sep 15, 2015 at 6:52 AM, Michael D. Setzer II >> <mi...@ku...> wrote: >> > During my C++ course last semester I had used dosemu to show the >> > students the old borland c++ compiler with linux using Fedora 21 and >> > dosemu to run the bc program and it worked great. Updated to Fedora 22 >> > over the summer, and course wasn't offered this semester, but earlier today >> > went in to check it out, and it kept crashing? >> > >> > dosemu would start just fine, but when I ran the bc program it was giving this >> > error? >> > >> > ERROR: SS selector invalid: 0x002B, type=0 np=0 >> > >> > Tried a number of options in config file, but found that this one finally made it >> > work again. >> > >> > $_cpu_emu = "full" >> > >> > Not sure if it was a change to the Fedora 22, or the newer kernels or what. >> > Tried a number of other options, but this was what stopped the error, and >> > had the program come up. Went back to the original config file, and just >> > changed this one to make sure that it was what made the difference. >> > >> > >> > +----------------------------------------------------------+ >> > Michael D. Setzer II - Computer Science Instructor >> > Guam Community College Computer Center >> > mailto:mi...@ku... >> > mailto:mse...@gm... >> > http://www.guam.net/home/mikes >> > Guam - Where America's Day Begins >> > G4L Disk Imaging Project maintainer >> > http://sourceforge.net/projects/g4l/ >> > +----------------------------------------------------------+ >> > >> > http://setiathome.berkeley.edu (Original) >> > Number of Seti Units Returned: 19,471 >> > Processing time: 32 years, 290 days, 12 hours, 58 minutes >> > (Total Hours: 287,489) >> > >> > BOINC@HOME CREDITS >> > ROSETTA 34280054.277468 | SETI 61931064.810280 >> > ABC 16613838.513356 | EINSTEIN 71699905.601494 >> > >> > >> > ------------------------------------------------------------------------------ >> > _______________________________________________ >> > Dosemu-devel mailing list >> > Dos...@li... >> > https://lists.sourceforge.net/lists/listinfo/dosemu-devel > > > +----------------------------------------------------------+ > Michael D. Setzer II - Computer Science Instructor > Guam Community College Computer Center > mailto:mi...@ku... > mailto:mse...@gm... > http://www.guam.net/home/mikes > Guam - Where America's Day Begins > G4L Disk Imaging Project maintainer > http://sourceforge.net/projects/g4l/ > +----------------------------------------------------------+ > > http://setiathome.berkeley.edu (Original) > Number of Seti Units Returned: 19,471 > Processing time: 32 years, 290 days, 12 hours, 58 minutes > (Total Hours: 287,489) > > BOINC@HOME CREDITS > ROSETTA 34330519.615760 | SETI 62153655.309010 > ABC 16613838.513356 | EINSTEIN 71839579.345494 > | 
| 
      
      
      From: solarflow99 <sol...@gm...> - 2015-09-15 23:51:52
      
     | 
| is this 64 bit? are you using the RPM? On Tue, Sep 15, 2015 at 6:52 AM, Michael D. Setzer II <mi...@ku...> wrote: > During my C++ course last semester I had used dosemu to show the > students the old borland c++ compiler with linux using Fedora 21 and > dosemu to run the bc program and it worked great. Updated to Fedora 22 > over the summer, and course wasn't offered this semester, but earlier today > went in to check it out, and it kept crashing? > > dosemu would start just fine, but when I ran the bc program it was giving this > error? > > ERROR: SS selector invalid: 0x002B, type=0 np=0 > > Tried a number of options in config file, but found that this one finally made it > work again. > > $_cpu_emu = "full" > > Not sure if it was a change to the Fedora 22, or the newer kernels or what. > Tried a number of other options, but this was what stopped the error, and > had the program come up. Went back to the original config file, and just > changed this one to make sure that it was what made the difference. > > > +----------------------------------------------------------+ > Michael D. Setzer II - Computer Science Instructor > Guam Community College Computer Center > mailto:mi...@ku... > mailto:mse...@gm... > http://www.guam.net/home/mikes > Guam - Where America's Day Begins > G4L Disk Imaging Project maintainer > http://sourceforge.net/projects/g4l/ > +----------------------------------------------------------+ > > http://setiathome.berkeley.edu (Original) > Number of Seti Units Returned: 19,471 > Processing time: 32 years, 290 days, 12 hours, 58 minutes > (Total Hours: 287,489) > > BOINC@HOME CREDITS > ROSETTA 34280054.277468 | SETI 61931064.810280 > ABC 16613838.513356 | EINSTEIN 71699905.601494 > > > ------------------------------------------------------------------------------ > _______________________________________________ > Dosemu-devel mailing list > Dos...@li... > https://lists.sourceforge.net/lists/listinfo/dosemu-devel | 
| 
      
      
      From: Michael D. S. I. <mi...@ku...> - 2015-09-15 14:10:11
      
     | 
| During my C++ course last semester I had used dosemu to show the students the old borland c++ compiler with linux using Fedora 21 and dosemu to run the bc program and it worked great. Updated to Fedora 22 over the summer, and course wasn't offered this semester, but earlier today went in to check it out, and it kept crashing? dosemu would start just fine, but when I ran the bc program it was giving this error? ERROR: SS selector invalid: 0x002B, type=0 np=0 Tried a number of options in config file, but found that this one finally made it work again. $_cpu_emu = "full" Not sure if it was a change to the Fedora 22, or the newer kernels or what. Tried a number of other options, but this was what stopped the error, and had the program come up. Went back to the original config file, and just changed this one to make sure that it was what made the difference. +----------------------------------------------------------+ Michael D. Setzer II - Computer Science Instructor Guam Community College Computer Center mailto:mi...@ku... mailto:mse...@gm... http://www.guam.net/home/mikes Guam - Where America's Day Begins G4L Disk Imaging Project maintainer http://sourceforge.net/projects/g4l/ +----------------------------------------------------------+ http://setiathome.berkeley.edu (Original) Number of Seti Units Returned: 19,471 Processing time: 32 years, 290 days, 12 hours, 58 minutes (Total Hours: 287,489) BOINC@HOME CREDITS ROSETTA 34280054.277468 | SETI 61931064.810280 ABC 16613838.513356 | EINSTEIN 71699905.601494 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 18:35:55
      
     | 
| From: "Ryan C. Underwood" <ne...@ic...>
Now the user can start consuming MIDI data after dosemu has started,
instead of having to start over after realizing he forgot to start
his MIDI-consuming app.
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 src/plugin/midimisc/mid_o_pipe.c | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/src/plugin/midimisc/mid_o_pipe.c b/src/plugin/midimisc/mid_o_pipe.c
index eb45f64..633e3eb 100644
--- a/src/plugin/midimisc/mid_o_pipe.c
+++ b/src/plugin/midimisc/mid_o_pipe.c
@@ -41,10 +41,16 @@ static int midopipe_init(void)
     pipe_fd =
 	RPT_SYSCALL(open(name, O_WRONLY | O_CREAT | O_NONBLOCK, 0666));
     if (pipe_fd == -1) {
-	S_printf("%s: unable to open %s for writing: %s\n",
-		 midopipe_name, name, strerror(errno));
-	return 0;
+	int err = errno;
+	S_printf("%s: unable to open %s for writing (%s)%s\n", midopipe_name, name,
+	    strerror(errno), errno == ENXIO ? ", will continue trying" : "");
+	if (err == ENXIO) { /* no FIFO readers */
+	    return 1;
+	} else { /* some other problem */
+	   return 0;
+	}
     }
+    /* open ok */
     return 1;
 }
 
@@ -62,9 +68,28 @@ static void midopipe_reset(void)
 
 static void midopipe_write(unsigned char val)
 {
-    if (pipe_fd == -1)
-	return;
-    write(pipe_fd, &val, 1);
+    /* Try again to open FIFO on each write in case some readers showed up. */
+    if (pipe_fd == -1) {
+	pipe_fd = RPT_SYSCALL(open(DOSEMU_MIDI_PATH, O_WRONLY | O_CREAT | O_NONBLOCK, 0666));
+	if (pipe_fd == -1) {
+	    return;
+	}
+    }
+    int retry = 0;
+    do {
+	if (write(pipe_fd, &val, 1) == -1) {
+	    switch (errno) {
+		case EAGAIN:
+		case EINTR:
+		    retry = 1;
+		default: /* all other errors incl. EPIPE */
+		    close(pipe_fd);
+		    pipe_fd = -1;
+		    retry = 0;
+		    break;
+	    }
+	}
+    } while (retry);
 }
 
 CONSTRUCTOR(static int midopipe_register(void))
-- 
1.9.1
 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 18:26:47
      
     | 
| From: Ryan Underwood <ne...@ic...>
XRandR support is fully added and works properly in a multihead configuration
if the user's version is at least 1.2.  It works basically like the existing
XVidMode code and is preferred whenever it is available.  It will also properly
restore the dosemu window's position when exiting fullscreen mode.
Keyboard and mouse grabbing had to be reworked to account for multihead (e.g.,
fullscreen DOS window on one output but with the ability to use applications on
a different output).
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 configure               |  80 +++++++++++++-
 configure.ac            |  17 +++
 src/include/config.h.in |   3 +
 src/plugin/X/X.c        | 280 ++++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 332 insertions(+), 48 deletions(-)
diff --git a/configure b/configure
index 1faf59f..bfa49e0 100755
--- a/configure
+++ b/configure
@@ -746,6 +746,7 @@ with_slangdir
 with_x
 enable_mitshm
 enable_vidmode
+enable_xrandr
 enable_experimental
 enable_debug
 enable_aspi
@@ -1382,6 +1383,7 @@ Optional Features:
   --disable-dlplugins     do NOT use dynamically loaded plugins
   --disable-mitshm        do NOT use the MITSHM X extension
   --enable-vidmode        use XF86 vidmode extension
+{  --disable-xrandr        do NOT use the XRandR extension]
   --enable-experimental   enable configuration of EXPERIMENTAL stuff
   --enable-debug          compile with debug info
   --disable-aspi          do NOT compile with ASPI support
@@ -3740,7 +3742,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3786,7 +3788,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3810,7 +3812,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3855,7 +3857,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3879,7 +3881,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -5894,6 +5896,72 @@ fi
 
     fi
 
+    # Check whether --enable-xrandr was given.
+if test "${enable_xrandr+set}" = set; then :
+  enableval=$enable_xrandr;
+fi
+
+    if test "$enable_xrandr" != "no" ; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XRRQueryVersion in -lXrandr" >&5
+$as_echo_n "checking for XRRQueryVersion in -lXrandr... " >&6; }
+if ${ac_cv_lib_Xrandr_XRRQueryVersion+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXrandr  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XRRQueryVersion ();
+int
+main ()
+{
+return XRRQueryVersion ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_Xrandr_XRRQueryVersion=yes
+else
+  ac_cv_lib_Xrandr_XRRQueryVersion=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xrandr_XRRQueryVersion" >&5
+$as_echo "$ac_cv_lib_Xrandr_XRRQueryVersion" >&6; }
+if test "x$ac_cv_lib_Xrandr_XRRQueryVersion" = xyes; then :
+  enable_xrandr="yes"
+else
+  enable_xrandr="no"
+fi
+
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling without the XRandR extension" >&5
+$as_echo "$as_me: Compiling without the XRandR extension" >&6;}
+    else
+         ac_fn_c_check_header_compile "$LINENO" "X11/extensions/Xrandr.h" "ac_cv_header_X11_extensions_Xrandr_h" "#include <X11/Xlib.h>
+"
+if test "x$ac_cv_header_X11_extensions_Xrandr_h" = xyes; then :
+  $as_echo "#define HAVE_XRANDR 1" >>confdefs.h
+ X_LIBS="-lXrandr $X_LIBS"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling without the XRandR extension" >&5
+$as_echo "$as_me: Compiling without the XRandR extension" >&6;}
+fi
+
+
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -6325,6 +6393,8 @@ ac_config_commands="$ac_config_commands Makefile"
 
 
 
+
+
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
diff --git a/configure.ac b/configure.ac
index a5b4df9..f444b31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,6 +376,20 @@ if test "$have_x" = "yes" ; then
                  [#include <X11/Xlib.h>])
     fi
 
+    AC_ARG_ENABLE(xrandr,
+              {  --disable-xrandr        do NOT use the XRandR extension])
+    if test "$enable_xrandr" != "no" ; then
+      AC_CHECK_LIB(Xrandr, XRRQueryVersion, enable_xrandr="yes", enable_xrandr="no")
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               AC_MSG_NOTICE(Compiling without the XRandR extension)
+    else
+         AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+     [AC_DEFINE(HAVE_XRANDR,1) X_LIBS="-lXrandr $X_LIBS"],
+                 AC_MSG_NOTICE(Compiling without the XRandR extension),
+                 [#include <X11/Xlib.h>])
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -768,6 +782,9 @@ AH_TEMPLATE([HAVE_MITSHM],
 AH_TEMPLATE([HAVE_XVIDMODE],
 [ Define this if you want to use the XF86 video mode extension ])
 
+AH_TEMPLATE([HAVE_XRANDR],
+[ Define this if you want to use the XRandR extension ])
+
 AH_TEMPLATE([ASPI_SUPPORT],
 [ Define this for ASPI (generic SCSI) support ])
 
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 6ef8763..7cf2248 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -134,6 +134,9 @@ EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MID
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define this if you want to use the XRandR extension */
+#undef HAVE_XRANDR
+
 /* Define this if you want to use the XF86 video mode extension */
 #undef HAVE_XVIDMODE
 
diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c
index 8e188c8..6cb5b4b 100644
--- a/src/plugin/X/X.c
+++ b/src/plugin/X/X.c
@@ -235,6 +235,10 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include "emu.h"
 #include "timers.h"
 #include "bios.h"
@@ -320,6 +324,13 @@ static int modecount;
 static XF86VidModeModeInfo **vidmode_modes;
 #endif
 
+#ifdef HAVE_XRANDR
+static int xrandr_ok = 0;
+static RRMode xrandr_win_mode = None;
+static RRCrtc xrandr_win_crtc = None;
+static int xrandr_win_xpos, xrandr_win_ypos;
+#endif
+
 Display *display;		/* used in plugin/?/keyb_X_keycode.c */
 static int screen;
 static Visual *visual;
@@ -369,7 +380,7 @@ static unsigned ximage_bits_per_pixel;
 static unsigned ximage_mode;
 static vga_emu_update_type veut;
 
-static int grab_active = 0, kbd_grab_active = 0;
+static int grab_active = 0, kbd_grab_active = 0, force_kbd_grab = 0;
 #if CONFIG_X_MOUSE
 static char *grab_keystring = "Home";
 static KeySym grab_keysym = NoSymbol;
@@ -402,6 +413,10 @@ static void X_dga_done(void);
 static void X_xf86vm_init(void);
 static void X_xf86vm_done(void);
 #endif
+#ifdef HAVE_XRANDR
+static void X_randr_init(void);
+static void X_randr_done(void);
+#endif
 
 static void X_keymap_init(void);
 
@@ -432,7 +447,7 @@ static void resize_ximage(unsigned, unsigned);
 static int X_set_videomode(int, int, int);
 static void X_resize_text_screen(void);
 static void toggle_fullscreen_mode(int);
-static void X_vidmode(int w, int h, int *new_width, int *new_height);
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height);
 static void lock_window_size(unsigned wx_res, unsigned wy_res);
 
 /* screen update/redraw functions */
@@ -447,6 +462,7 @@ static Cursor create_invisible_cursor(void);
 /* text mode cursor manipulation stuff */
 static void X_update_cursor(void);
 
+static void toggle_kbd_grab(void);
 #if CONFIG_X_MOUSE
 /* mouse related code */
 static void set_mouse_position(int, int);
@@ -593,6 +609,10 @@ int X_init()
   X_xf86vm_init();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_init();
+#endif
+
   /* see if we find out something useful about our X server... -- sw */
   X_keymap_init();
 
@@ -806,6 +826,10 @@ void X_close()
   X_xf86vm_done();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_done();
+#endif
+
   X_load_text_font(display, 0, drawwindow, NULL, NULL, NULL);
   if(our_window) {
     XDestroyWindow(display, drawwindow);
@@ -1026,12 +1050,51 @@ static void X_xf86vm_init(void)
 static void X_xf86vm_done(void)
 {
   if (mainwindow == fullscreenwindow)
-    X_vidmode(-1, -1, &w_x_res, &w_y_res);
+    X_vidmode(-1, -1, NULL, NULL, &w_x_res, &w_y_res);
   xf86vm_ok = 0;
 }
 
 #endif
 
+#ifdef HAVE_XRANDR
+static void X_randr_init(void)
+{
+  int param1, param2;
+  if (XRRQueryExtension(display, ¶m1, ¶m2) &&
+      XRRQueryVersion(display, ¶m1, ¶m2))
+  {
+    X_printf("X: RandR Extension version %d.%d\n", param1, param2);
+    if (param1 <= 1 && param2 < 2) {
+      X_printf("X: RandR version doesn't support stretched desktop or multihead!\n");
+      /* continue anyway, as it should work for single head */
+    }
+    xrandr_ok = 1;
+  }
+}
+
+static void X_randr_exit_fullscreen(void)
+{
+  if (xrandr_win_crtc != None && xrandr_win_mode != None) {
+    X_printf("X: RandR restoring old mode %d crtc %d\n", (int)xrandr_win_mode, (int)xrandr_win_crtc);
+    XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+    XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, xrandr_win_crtc);
+    XRRSetCrtcConfig(display, sr, xrandr_win_crtc, CurrentTime, ci->x, ci->y, xrandr_win_mode, ci->rotation, ci->outputs, ci->noutput);
+    XRRFreeCrtcInfo(ci);
+    XRRFreeScreenResources(sr);
+    xrandr_win_crtc = xrandr_win_mode = None;
+  }
+}
+
+static void X_randr_done(void)
+{
+  if (mainwindow == fullscreenwindow) {
+    X_printf("X: RandR leaving fullscreen mode\n");
+    X_randr_exit_fullscreen();
+  }
+  xrandr_ok = 0;
+}
+#endif /* HAVE_XRANDR */
+
 /*
  * Handle 'auto'-entries in dosemu.conf, namely
  * $_X_keycode & $_layout
@@ -1229,15 +1292,15 @@ static void toggle_kbd_grab(void)
 {
   if(kbd_grab_active ^= 1) {
     X_printf("X: keyboard grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-    }
-  }
-  else {
+    XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+  } else {
     X_printf("X: keyboard grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabKeyboard(display, CurrentTime);
-    }
+    XUngrabKeyboard(display, CurrentTime);
+    /* In fullscreen, keyboard must always be grabbed if mouse is grabbed.
+     * If mouse is grabbed but keyboard is ungrabbed, there will be no way
+     * to refocus the fullscreen dosemu if it loses focus. */
+    if (mainwindow == fullscreenwindow && grab_active)
+      toggle_mouse_grab();
   }
   X_change_config(CHG_TITLE, NULL);
 }
@@ -1247,19 +1310,15 @@ static void toggle_mouse_grab(void)
   if(grab_active ^= 1) {
     config.mouse.use_absolute = 0;
     X_printf("X: mouse grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                   GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
-    }
+    XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(1);
   }
   else {
     config.mouse.use_absolute = 1;
     X_printf("X: mouse grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabPointer(display, CurrentTime);
-    }
+    XUngrabPointer(display, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_sync_coords(mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(0);
@@ -1338,7 +1397,7 @@ static void X_wait_unmapped(Window win)
 
 static void toggle_fullscreen_mode(int init)
 {
-  int resize_height, resize_width;
+  int reloc_x, reloc_y, resize_height, resize_width;
 
   if (!init) {
     XUnmapWindow(display, mainwindow);
@@ -1351,15 +1410,12 @@ static void toggle_fullscreen_mode(int init)
     toggling_fullscreen = 2;
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
-    if (!grab_active) {
-      toggle_mouse_grab();
-      force_grab = 1;
-    }
-    X_vidmode(x_res, y_res, &resize_width, &resize_height);
+    X_vidmode(x_res, y_res, &reloc_x, &reloc_y, &resize_width, &resize_height);
     mainwindow = fullscreenwindow;
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     } else {
       shift_x = (resize_width - w_x_res) / 2;
       shift_y = (resize_height - w_y_res) / 2;
@@ -1368,30 +1424,35 @@ static void toggle_fullscreen_mode(int init)
     XMapWindow(display, mainwindow);
     XRaiseWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, shift_x, shift_y);
-    XGrabPointer(display, drawwindow, True,
-                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                 GrabModeAsync, GrabModeAsync, drawwindow,  None,
-                 CurrentTime);
-    XGrabKeyboard(display, drawwindow, True, GrabModeAsync,
-                  GrabModeAsync, CurrentTime);
+    if (!grab_active) {
+      toggle_mouse_grab();
+      force_grab = 1;
+    }
+    if (!kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 1;
+    }
   } else {
     X_printf("X: entering windowed mode!\n");
     w_x_res = saved_w_x_res;
     w_y_res = saved_w_y_res;
-    XUngrabKeyboard(display, CurrentTime);
-    XUngrabPointer(display, CurrentTime);
     mainwindow = normalwindow;
-    X_vidmode(-1, -1, &resize_width, &resize_height);
+    X_vidmode(-1, -1, &reloc_x, &reloc_y, &resize_width, &resize_height);
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating dosemu window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     }
     XMapWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, 0, 0);
     if (force_grab && grab_active) {
       toggle_mouse_grab();
+      force_grab = 0;
+    }
+    if (force_kbd_grab && kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 0;
     }
-    force_grab = 0;
   }
   if(vga.mode_class == TEXT && !use_bitmap_font) {
     X_resize_text_screen();
@@ -1550,6 +1611,7 @@ static void X_handle_events(void)
               toggle_mouse_grab();
               break;
             } else if (keysym == XK_k) {
+              force_kbd_grab = 0;
               toggle_kbd_grab();
               break;
             } else if (keysym == XK_f) {
@@ -1652,6 +1714,12 @@ static void X_handle_events(void)
 	    }
 	    set_mouse_buttons(e.xcrossing.state);
 	    mouse_really_left_window = 0;
+	    /* Grab keyboard if fullscreen (i.e., entering window from another
+	     * CRTC in a multihead system.  Otherwise we can't type.*/
+	    if (mainwindow == fullscreenwindow && !kbd_grab_active) {
+	      toggle_kbd_grab();
+	      force_kbd_grab = 1;
+	    }
           }
 	  break;
 
@@ -1666,6 +1734,12 @@ static void X_handle_events(void)
             X_printf("X: bogus LeaveNotify event\n");
             mouse_really_left_window = 0;
           }
+	  /* Release keyboard if fullscreen, mouse leaves window, and the
+	   * current grab had been forced by dosemu. */
+	  if (mainwindow == fullscreenwindow && kbd_grab_active && force_kbd_grab) {
+	    toggle_kbd_grab();
+	    force_kbd_grab = 0;
+	  }
 	  break;
 
         case ConfigureNotify:
@@ -2066,7 +2140,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   sh.width = sh.min_width = sh.max_width = wx_res;
   sh.height = sh.min_height = sh.max_height = wy_res;
 
-  sh.flags = PSize  | PMinSize | PMaxSize;
+  sh.flags = PPosition | PSize | PMinSize | PMaxSize;
   if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect;
   if (use_bitmap_font) {
     sh.flags |= PResizeInc;
@@ -2086,7 +2160,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   x_fill = w_x_res;
   y_fill = w_y_res;
   if (mainwindow == fullscreenwindow)
-    X_vidmode(x_res, y_res, &x_fill, &y_fill);
+    X_vidmode(x_res, y_res, NULL, NULL, &x_fill, &y_fill);
 
   XResizeWindow(display, mainwindow, x_fill+1, y_fill+1);
 
@@ -2206,8 +2280,9 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
     lock_window_size(w_x_res, w_y_res);
+    /* lock_window_size() already did this, but there must be a reason ... */
     if(mainwindow == fullscreenwindow) {
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
     if (!use_bitmap_font) {
       w_x_res = saved_w_x_res;
@@ -2229,7 +2304,7 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     if(mainwindow == fullscreenwindow) {
       saved_w_x_res = w_x_res;
       saved_w_y_res = w_y_res;
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
 
     create_ximage();
@@ -2319,13 +2394,128 @@ void X_resize_text_screen()
 /*
  * Change to requested video mode or the closest greater one.
  */
-static void X_vidmode(int w, int h, int *new_width, int *new_height)
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height)
 {
   int nw, nh, mx, my, shift_x, shift_y;
 
   nw = DisplayWidth(display, screen);
   nh = DisplayHeight(display, screen);
 
+  int dosemu_x = -1, dosemu_y = -1;
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, rootwindow, &attr)) {
+    X_printf("X: X_vidmode: root window size (%d,%d)\n",
+        attr.width, attr.height);
+
+    Window child;
+    if (XTranslateCoordinates(display, normalwindow, rootwindow, 0, 0, &dosemu_x, &dosemu_y, &child)
+        && XGetWindowAttributes(display, normalwindow, &attr)) {
+      X_printf("X: X_vidmode: dosemu window loc (%d,%d) size (%d,%d)\n",
+          dosemu_x, dosemu_y, attr.width, attr.height);
+    }
+  }
+
+#ifdef HAVE_XRANDR
+  if (xrandr_ok) {
+    if (w == -1 && h == -1) {
+      /* Return to window. */
+      X_printf("X: RandR leaving fullscreen mode\n");
+      X_randr_exit_fullscreen();
+			dosemu_x = xrandr_win_xpos;
+			dosemu_y = xrandr_win_ypos;
+    } else if (mainwindow != fullscreenwindow) {
+      X_printf("X: RandR entering fullscreen mode\n");
+      /* Find which CRTC 'window' dosemu's upper left corner is within. */
+      XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+      RRCrtc crtc = None;
+			int i;
+      for (i = 0; i < sr->ncrtc; i++) {
+        XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, sr->crtcs[i]);
+        if (ci->mode == None) {
+          /* crtc disabled, try another */
+          XRRFreeCrtcInfo(ci);
+          continue;
+        }
+        X_printf("X: RandR considering CRTC (%d+%d,%d+%d)\n", ci->x, ci->width, ci->y, ci->height);
+        if (dosemu_x >= ci->x && dosemu_x < ci->x + ci->width &&
+            dosemu_y >= ci->y && dosemu_y < ci->y + ci->height)
+        {
+          X_printf("X: RandR using this CRTC\n");
+          crtc = sr->crtcs[i];
+          XRRFreeCrtcInfo(ci);
+          break;
+        }
+        XRRFreeCrtcInfo(ci);
+      }
+      if (crtc == None) {
+        error("X: RandR found no suitable CRTC!\n");
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, crtc);
+
+      /* XXX: Use the first CRTC output always.  In what display configuration
+       * could this break? */
+      int output_idx = 0;
+      XRROutputInfo *oi = XRRGetOutputInfo(display, sr, ci->outputs[output_idx]);
+
+      /* Find the best mode supported by this CRTC by first finding the
+       * closest fit that is at least as large as the DOS screen, then the
+       * best refresh rate at that size.  To do this we have to find every mode
+       * available in the output, then search the screen modes for its ID. */
+      int mode_id = -1;
+      int best_rate = 0;
+      for (i = 0; i < oi->nmode; i++) {
+        RRMode output_mode = oi->modes[i];
+				int j;
+        for (j = 0; j < sr->nmode; j++) {
+          const XRRModeInfo *mi = &sr->modes[j];
+          if (mi->id != output_mode)
+            continue;
+          int width = mi->width;
+          int height = mi->height;
+          X_printf("X: RandR considering mode (%d,%d)\n", width, height);
+          if (width >= w && height >= h && width <= nw && height <= nh) {
+            if (width != nw || height != nh)
+              best_rate = 0; /* geometry changed, start over rate search */
+            nw = width;
+            nh = height;
+            int rate = mi->dotClock / (mi->hTotal * mi->vTotal);
+            if (rate > best_rate) {
+              best_rate = rate;
+              mode_id = mi->id;
+            }
+          }
+        }
+      }
+      if (mode_id == -1) {
+        error("X: RandR found no suitable mode for CRTC output %d!\n", output_idx);
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRFreeOutputInfo(oi);
+
+      /* Change to fullscreen; save window config first. */
+      X_printf("X: RandR mode asking for (%d,%d); setting %dx%d@%d mode %d\n", w, h, nw, nh, best_rate, mode_id);
+      X_printf("X: RandR saving old mode %d crtc %d\n", (int)ci->mode, (int)crtc);
+      xrandr_win_mode = ci->mode;
+      xrandr_win_crtc = crtc;
+			xrandr_win_xpos = dosemu_x;
+			xrandr_win_ypos = dosemu_y;
+			/* Position window at (0,0) on *this* CRTC. */
+			dosemu_x = ci->x;
+			dosemu_y = ci->y;
+      XRRSetCrtcConfig(display, sr, crtc, CurrentTime, ci->x, ci->y, mode_id, ci->rotation, ci->outputs, ci->noutput);
+      XRRFreeCrtcInfo(ci);
+      XRRFreeScreenResources(sr);
+      /* Callers always set this themselves, but anyway... */
+      mainwindow = fullscreenwindow;
+    }
+  } else /* Only attempt VidMode or non-modechange fullscreen if RandR is disabled. */
+#endif /* HAVE_XRANDR */
+
 #ifdef HAVE_XVIDMODE
   if (xf86vm_ok) {
     static XF86VidModeModeLine vidmode_modeline;
@@ -2402,6 +2592,10 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height)
     XWarpPointer(display, None, drawwindow, 0, 0, 0, 0, mx, my);
   *new_width = nw;
   *new_height = nh;
+  if (new_x != NULL)
+    *new_x = dosemu_x;
+  if (new_y != NULL)
+    *new_y = dosemu_y;
 }
 
 /*
-- 
1.9.1
 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 18:09:29
      
     | 
| From: Ryan Underwood <ne...@ic...>
XRandR support is fully added and works properly in a multihead configuration
if the user's version is at least 1.2.  It works basically like the existing
XVidMode code and is preferred whenever it is available.  It will also properly
restore the dosemu window's position when exiting fullscreen mode.
Keyboard and mouse grabbing had to be reworked to account for multihead (e.g.,
fullscreen DOS window on one output but with the ability to use applications on
a different output).
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 configure               |  80 +++++++++++++-
 configure.ac            |  17 +++
 src/include/config.h.in |   3 +
 src/plugin/X/X.c        | 280 ++++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 332 insertions(+), 48 deletions(-)
diff --git a/configure b/configure
index 2d3dbac..2b1907d 100755
--- a/configure
+++ b/configure
@@ -749,6 +749,7 @@ with_slangdir
 with_x
 enable_mitshm
 enable_vidmode
+enable_xrandr
 enable_experimental
 enable_debug
 enable_aspi
@@ -1387,6 +1388,7 @@ Optional Features:
   --disable-dlplugins     do NOT use dynamically loaded plugins
   --disable-mitshm        do NOT use the MITSHM X extension
   --enable-vidmode        use XF86 vidmode extension
+{  --disable-xrandr        do NOT use the XRandR extension]
   --enable-experimental   enable configuration of EXPERIMENTAL stuff
   --enable-debug          compile with debug info
   --disable-aspi          do NOT compile with ASPI support
@@ -3749,7 +3751,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3795,7 +3797,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3819,7 +3821,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3864,7 +3866,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3888,7 +3890,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -5903,6 +5905,72 @@ fi
 
     fi
 
+    # Check whether --enable-xrandr was given.
+if test "${enable_xrandr+set}" = set; then :
+  enableval=$enable_xrandr;
+fi
+
+    if test "$enable_xrandr" != "no" ; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XRRQueryVersion in -lXrandr" >&5
+$as_echo_n "checking for XRRQueryVersion in -lXrandr... " >&6; }
+if ${ac_cv_lib_Xrandr_XRRQueryVersion+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXrandr  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XRRQueryVersion ();
+int
+main ()
+{
+return XRRQueryVersion ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_Xrandr_XRRQueryVersion=yes
+else
+  ac_cv_lib_Xrandr_XRRQueryVersion=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xrandr_XRRQueryVersion" >&5
+$as_echo "$ac_cv_lib_Xrandr_XRRQueryVersion" >&6; }
+if test "x$ac_cv_lib_Xrandr_XRRQueryVersion" = xyes; then :
+  enable_xrandr="yes"
+else
+  enable_xrandr="no"
+fi
+
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling without the XRandR extension" >&5
+$as_echo "$as_me: Compiling without the XRandR extension" >&6;}
+    else
+         ac_fn_c_check_header_compile "$LINENO" "X11/extensions/Xrandr.h" "ac_cv_header_X11_extensions_Xrandr_h" "#include <X11/Xlib.h>
+"
+if test "x$ac_cv_header_X11_extensions_Xrandr_h" = xyes; then :
+  $as_echo "#define HAVE_XRANDR 1" >>confdefs.h
+ X_LIBS="-lXrandr $X_LIBS"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling without the XRandR extension" >&5
+$as_echo "$as_me: Compiling without the XRandR extension" >&6;}
+fi
+
+
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -6342,6 +6410,8 @@ ac_config_commands="$ac_config_commands Makefile"
 
 
 
+
+
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
diff --git a/configure.ac b/configure.ac
index 18bf933..2a6bd56 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,6 +376,20 @@ if test "$have_x" = "yes" ; then
                  [#include <X11/Xlib.h>])
     fi
 
+    AC_ARG_ENABLE(xrandr,
+              {  --disable-xrandr        do NOT use the XRandR extension])
+    if test "$enable_xrandr" != "no" ; then
+      AC_CHECK_LIB(Xrandr, XRRQueryVersion, enable_xrandr="yes", enable_xrandr="no")
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               AC_MSG_NOTICE(Compiling without the XRandR extension)
+    else
+         AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+     [AC_DEFINE(HAVE_XRANDR,1) X_LIBS="-lXrandr $X_LIBS"],
+                 AC_MSG_NOTICE(Compiling without the XRandR extension),
+                 [#include <X11/Xlib.h>])
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -770,6 +784,9 @@ AH_TEMPLATE([HAVE_MITSHM],
 AH_TEMPLATE([HAVE_XVIDMODE],
 [ Define this if you want to use the XF86 video mode extension ])
 
+AH_TEMPLATE([HAVE_XRANDR],
+[ Define this if you want to use the XRandR extension ])
+
 AH_TEMPLATE([ASPI_SUPPORT],
 [ Define this for ASPI (generic SCSI) support ])
 
diff --git a/src/include/config.h.in b/src/include/config.h.in
index b7e2ea4..08d8da8 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -128,6 +128,9 @@ EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MID
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define this if you want to use the XRandR extension */
+#undef HAVE_XRANDR
+
 /* Define this if you want to use the XF86 video mode extension */
 #undef HAVE_XVIDMODE
 
diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c
index 7782f36..494b0be 100644
--- a/src/plugin/X/X.c
+++ b/src/plugin/X/X.c
@@ -235,6 +235,10 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include "emu.h"
 #include "timers.h"
 #include "bios.h"
@@ -320,6 +324,13 @@ static int modecount;
 static XF86VidModeModeInfo **vidmode_modes;
 #endif
 
+#ifdef HAVE_XRANDR
+static int xrandr_ok = 0;
+static RRMode xrandr_win_mode = None;
+static RRCrtc xrandr_win_crtc = None;
+static int xrandr_win_xpos, xrandr_win_ypos;
+#endif
+
 Display *display;		/* used in plugin/?/keyb_X_keycode.c */
 static int screen;
 static Visual *visual;
@@ -369,7 +380,7 @@ static int w_x_res, w_y_res;		/* actual window size */
 static int saved_w_x_res, saved_w_y_res;	/* saved normal window size */
 static unsigned ximage_bits_per_pixel;
 
-static int grab_active = 0, kbd_grab_active = 0;
+static int grab_active = 0, kbd_grab_active = 0, force_kbd_grab = 0;
 #if CONFIG_X_MOUSE
 static char *grab_keystring = "Home";
 static KeySym grab_keysym = NoSymbol;
@@ -402,6 +413,10 @@ static void X_dga_done(void);
 static void X_xf86vm_init(void);
 static void X_xf86vm_done(void);
 #endif
+#ifdef HAVE_XRANDR
+static void X_randr_init(void);
+static void X_randr_done(void);
+#endif
 
 static void X_keymap_init(void);
 
@@ -429,7 +444,7 @@ static void resize_ximage(unsigned, unsigned);
 static int X_set_videomode(int, int, int);
 static void X_resize_text_screen(void);
 static void toggle_fullscreen_mode(int);
-static void X_vidmode(int w, int h, int *new_width, int *new_height);
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height);
 static void lock_window_size(unsigned wx_res, unsigned wy_res);
 
 /* screen update/redraw functions */
@@ -440,6 +455,7 @@ static int X_update_screen(void);
 static void load_cursor_shapes(void);
 static Cursor create_invisible_cursor(void);
 
+static void toggle_kbd_grab(void);
 #if CONFIG_X_MOUSE
 /* mouse related code */
 static void set_mouse_position(int, int);
@@ -602,6 +618,10 @@ int X_init()
   X_xf86vm_init();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_init();
+#endif
+
   /* see if we find out something useful about our X server... -- sw */
   X_keymap_init();
 
@@ -822,6 +842,10 @@ void X_close()
   X_xf86vm_done();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_done();
+#endif
+
   if(our_window) {
     XDestroyWindow(display, drawwindow);
     XDestroyWindow(display, normalwindow);
@@ -1039,12 +1063,51 @@ static void X_xf86vm_init(void)
 static void X_xf86vm_done(void)
 {
   if (mainwindow == fullscreenwindow)
-    X_vidmode(-1, -1, &w_x_res, &w_y_res);
+    X_vidmode(-1, -1, NULL, NULL, &w_x_res, &w_y_res);
   xf86vm_ok = 0;
 }
 
 #endif
 
+#ifdef HAVE_XRANDR
+static void X_randr_init(void)
+{
+  int param1, param2;
+  if (XRRQueryExtension(display, ¶m1, ¶m2) &&
+      XRRQueryVersion(display, ¶m1, ¶m2))
+  {
+    X_printf("X: RandR Extension version %d.%d\n", param1, param2);
+    if (param1 <= 1 && param2 < 2) {
+      X_printf("X: RandR version doesn't support stretched desktop or multihead!\n");
+      /* continue anyway, as it should work for single head */
+    }
+    xrandr_ok = 1;
+  }
+}
+
+static void X_randr_exit_fullscreen(void)
+{
+  if (xrandr_win_crtc != None && xrandr_win_mode != None) {
+    X_printf("X: RandR restoring old mode %d crtc %d\n", (int)xrandr_win_mode, (int)xrandr_win_crtc);
+    XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+    XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, xrandr_win_crtc);
+    XRRSetCrtcConfig(display, sr, xrandr_win_crtc, CurrentTime, ci->x, ci->y, xrandr_win_mode, ci->rotation, ci->outputs, ci->noutput);
+    XRRFreeCrtcInfo(ci);
+    XRRFreeScreenResources(sr);
+    xrandr_win_crtc = xrandr_win_mode = None;
+  }
+}
+
+static void X_randr_done(void)
+{
+  if (mainwindow == fullscreenwindow) {
+    X_printf("X: RandR leaving fullscreen mode\n");
+    X_randr_exit_fullscreen();
+  }
+  xrandr_ok = 0;
+}
+#endif /* HAVE_XRANDR */
+
 /*
  * Handle 'auto'-entries in dosemu.conf, namely
  * $_X_keycode & $_layout
@@ -1243,15 +1306,15 @@ static void toggle_kbd_grab(void)
 {
   if(kbd_grab_active ^= 1) {
     X_printf("X: keyboard grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-    }
-  }
-  else {
+    XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+  } else {
     X_printf("X: keyboard grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabKeyboard(display, CurrentTime);
-    }
+    XUngrabKeyboard(display, CurrentTime);
+    /* In fullscreen, keyboard must always be grabbed if mouse is grabbed.
+     * If mouse is grabbed but keyboard is ungrabbed, there will be no way
+     * to refocus the fullscreen dosemu if it loses focus. */
+    if (mainwindow == fullscreenwindow && grab_active)
+      toggle_mouse_grab();
   }
   X_change_config(CHG_TITLE, NULL);
 }
@@ -1261,19 +1324,15 @@ static void toggle_mouse_grab(void)
   if(grab_active ^= 1) {
     config.mouse.use_absolute = 0;
     X_printf("X: mouse grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                   GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
-    }
+    XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(1);
   }
   else {
     config.mouse.use_absolute = 1;
     X_printf("X: mouse grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabPointer(display, CurrentTime);
-    }
+    XUngrabPointer(display, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_sync_coords(mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(0);
@@ -1369,7 +1428,7 @@ static void X_wait_unmapped(Window win)
 
 static void toggle_fullscreen_mode(int init)
 {
-  int resize_height, resize_width;
+  int reloc_x, reloc_y, resize_height, resize_width;
 
   if (!init) {
     XUnmapWindow(display, mainwindow);
@@ -1382,15 +1441,12 @@ static void toggle_fullscreen_mode(int init)
     toggling_fullscreen = 2;
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
-    if (!grab_active) {
-      toggle_mouse_grab();
-      force_grab = 1;
-    }
-    X_vidmode(x_res, y_res, &resize_width, &resize_height);
+    X_vidmode(x_res, y_res, &reloc_x, &reloc_y, &resize_width, &resize_height);
     mainwindow = fullscreenwindow;
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width, resize_height);
-      XResizeWindow(display, drawwindow, resize_width, resize_height);
+      X_printf("X: relocating window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     } else {
       shift_x = (resize_width - w_x_res) / 2;
       shift_y = (resize_height - w_y_res) / 2;
@@ -1399,30 +1455,35 @@ static void toggle_fullscreen_mode(int init)
     XMapWindow(display, mainwindow);
     XRaiseWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, shift_x, shift_y);
-    XGrabPointer(display, drawwindow, True,
-                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                 GrabModeAsync, GrabModeAsync, drawwindow,  None,
-                 CurrentTime);
-    XGrabKeyboard(display, drawwindow, True, GrabModeAsync,
-                  GrabModeAsync, CurrentTime);
+    if (!grab_active) {
+      toggle_mouse_grab();
+      force_grab = 1;
+    }
+    if (!kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 1;
+    }
   } else {
     X_printf("X: entering windowed mode!\n");
     w_x_res = saved_w_x_res;
     w_y_res = saved_w_y_res;
-    XUngrabKeyboard(display, CurrentTime);
-    XUngrabPointer(display, CurrentTime);
     mainwindow = normalwindow;
-    X_vidmode(-1, -1, &resize_width, &resize_height);
+    X_vidmode(-1, -1, &reloc_x, &reloc_y, &resize_width, &resize_height);
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width, resize_height);
-      XResizeWindow(display, drawwindow, resize_width, resize_height);
+      X_printf("X: relocating dosemu window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     }
     XMapWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, 0, 0);
     if (force_grab && grab_active) {
       toggle_mouse_grab();
+      force_grab = 0;
+    }
+    if (force_kbd_grab && kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 0;
     }
-    force_grab = 0;
   }
   if(vga.mode_class == TEXT && !use_bitmap_font) {
     X_resize_text_screen();
@@ -1578,6 +1639,7 @@ static int __X_handle_events(void)
               toggle_mouse_grab();
               break;
             } else if (keysym == XK_k) {
+              force_kbd_grab = 0;
               toggle_kbd_grab();
               break;
             } else if (keysym == XK_f) {
@@ -1680,6 +1742,12 @@ static int __X_handle_events(void)
 	    }
 	    set_mouse_buttons(e.xcrossing.state);
 	    mouse_really_left_window = 0;
+	    /* Grab keyboard if fullscreen (i.e., entering window from another
+	     * CRTC in a multihead system.  Otherwise we can't type.*/
+	    if (mainwindow == fullscreenwindow && !kbd_grab_active) {
+	      toggle_kbd_grab();
+	      force_kbd_grab = 1;
+	    }
           }
 	  break;
 
@@ -1694,6 +1762,12 @@ static int __X_handle_events(void)
             X_printf("X: bogus LeaveNotify event\n");
             mouse_really_left_window = 0;
           }
+	  /* Release keyboard if fullscreen, mouse leaves window, and the
+	   * current grab had been forced by dosemu. */
+	  if (mainwindow == fullscreenwindow && kbd_grab_active && force_kbd_grab) {
+	    toggle_kbd_grab();
+	    force_kbd_grab = 0;
+	  }
 	  break;
 
         case ConfigureNotify:
@@ -2074,7 +2148,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   sh.base_width = sh.width = sh.min_width = sh.max_width = wx_res;
   sh.base_height = sh.height = sh.min_height = sh.max_height = wy_res;
 
-  sh.flags = PSize  | PMinSize | PMaxSize | PBaseSize;
+  sh.flags = PPosition | PSize | PMinSize | PMaxSize;
   if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect;
   if (use_bitmap_font) {
 #if 1
@@ -2101,7 +2175,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   x_fill = wx_res;
   y_fill = wy_res;
   if (mainwindow == fullscreenwindow)
-    X_vidmode(x_res, y_res, &x_fill, &y_fill);
+    X_vidmode(x_res, y_res, NULL, NULL, &x_fill, &y_fill);
 
   XResizeWindow(display, mainwindow, x_fill, y_fill);
 
@@ -2211,8 +2285,9 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
     lock_window_size(w_x_res, w_y_res);
+    /* lock_window_size() already did this, but there must be a reason ... */
     if(mainwindow == fullscreenwindow) {
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
     if (!use_bitmap_font) {
       w_x_res = saved_w_x_res;
@@ -2234,7 +2309,7 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     if(mainwindow == fullscreenwindow) {
       saved_w_x_res = w_x_res;
       saved_w_y_res = w_y_res;
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
 
     create_ximage();
@@ -2300,13 +2375,128 @@ void X_resize_text_screen()
 /*
  * Change to requested video mode or the closest greater one.
  */
-static void X_vidmode(int w, int h, int *new_width, int *new_height)
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height)
 {
   int nw, nh, mx, my, shift_x, shift_y;
 
   nw = DisplayWidth(display, screen);
   nh = DisplayHeight(display, screen);
 
+  int dosemu_x = -1, dosemu_y = -1;
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, rootwindow, &attr)) {
+    X_printf("X: X_vidmode: root window size (%d,%d)\n",
+        attr.width, attr.height);
+
+    Window child;
+    if (XTranslateCoordinates(display, normalwindow, rootwindow, 0, 0, &dosemu_x, &dosemu_y, &child)
+        && XGetWindowAttributes(display, normalwindow, &attr)) {
+      X_printf("X: X_vidmode: dosemu window loc (%d,%d) size (%d,%d)\n",
+          dosemu_x, dosemu_y, attr.width, attr.height);
+    }
+  }
+
+#ifdef HAVE_XRANDR
+  if (xrandr_ok) {
+    if (w == -1 && h == -1) {
+      /* Return to window. */
+      X_printf("X: RandR leaving fullscreen mode\n");
+      X_randr_exit_fullscreen();
+			dosemu_x = xrandr_win_xpos;
+			dosemu_y = xrandr_win_ypos;
+    } else if (mainwindow != fullscreenwindow) {
+      X_printf("X: RandR entering fullscreen mode\n");
+      /* Find which CRTC 'window' dosemu's upper left corner is within. */
+      XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+      RRCrtc crtc = None;
+			int i;
+      for (i = 0; i < sr->ncrtc; i++) {
+        XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, sr->crtcs[i]);
+        if (ci->mode == None) {
+          /* crtc disabled, try another */
+          XRRFreeCrtcInfo(ci);
+          continue;
+        }
+        X_printf("X: RandR considering CRTC (%d+%d,%d+%d)\n", ci->x, ci->width, ci->y, ci->height);
+        if (dosemu_x >= ci->x && dosemu_x < ci->x + ci->width &&
+            dosemu_y >= ci->y && dosemu_y < ci->y + ci->height)
+        {
+          X_printf("X: RandR using this CRTC\n");
+          crtc = sr->crtcs[i];
+          XRRFreeCrtcInfo(ci);
+          break;
+        }
+        XRRFreeCrtcInfo(ci);
+      }
+      if (crtc == None) {
+        error("X: RandR found no suitable CRTC!\n");
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, crtc);
+
+      /* XXX: Use the first CRTC output always.  In what display configuration
+       * could this break? */
+      int output_idx = 0;
+      XRROutputInfo *oi = XRRGetOutputInfo(display, sr, ci->outputs[output_idx]);
+
+      /* Find the best mode supported by this CRTC by first finding the
+       * closest fit that is at least as large as the DOS screen, then the
+       * best refresh rate at that size.  To do this we have to find every mode
+       * available in the output, then search the screen modes for its ID. */
+      int mode_id = -1;
+      int best_rate = 0;
+      for (i = 0; i < oi->nmode; i++) {
+        RRMode output_mode = oi->modes[i];
+				int j;
+        for (j = 0; j < sr->nmode; j++) {
+          const XRRModeInfo *mi = &sr->modes[j];
+          if (mi->id != output_mode)
+            continue;
+          int width = mi->width;
+          int height = mi->height;
+          X_printf("X: RandR considering mode (%d,%d)\n", width, height);
+          if (width >= w && height >= h && width <= nw && height <= nh) {
+            if (width != nw || height != nh)
+              best_rate = 0; /* geometry changed, start over rate search */
+            nw = width;
+            nh = height;
+            int rate = mi->dotClock / (mi->hTotal * mi->vTotal);
+            if (rate > best_rate) {
+              best_rate = rate;
+              mode_id = mi->id;
+            }
+          }
+        }
+      }
+      if (mode_id == -1) {
+        error("X: RandR found no suitable mode for CRTC output %d!\n", output_idx);
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRFreeOutputInfo(oi);
+
+      /* Change to fullscreen; save window config first. */
+      X_printf("X: RandR mode asking for (%d,%d); setting %dx%d@%d mode %d\n", w, h, nw, nh, best_rate, mode_id);
+      X_printf("X: RandR saving old mode %d crtc %d\n", (int)ci->mode, (int)crtc);
+      xrandr_win_mode = ci->mode;
+      xrandr_win_crtc = crtc;
+			xrandr_win_xpos = dosemu_x;
+			xrandr_win_ypos = dosemu_y;
+			/* Position window at (0,0) on *this* CRTC. */
+			dosemu_x = ci->x;
+			dosemu_y = ci->y;
+      XRRSetCrtcConfig(display, sr, crtc, CurrentTime, ci->x, ci->y, mode_id, ci->rotation, ci->outputs, ci->noutput);
+      XRRFreeCrtcInfo(ci);
+      XRRFreeScreenResources(sr);
+      /* Callers always set this themselves, but anyway... */
+      mainwindow = fullscreenwindow;
+    }
+  } else /* Only attempt VidMode or non-modechange fullscreen if RandR is disabled. */
+#endif /* HAVE_XRANDR */
+
 #ifdef HAVE_XVIDMODE
   if (xf86vm_ok) {
     static XF86VidModeModeLine vidmode_modeline;
@@ -2383,6 +2573,10 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height)
     XWarpPointer(display, None, drawwindow, 0, 0, 0, 0, mx, my);
   *new_width = nw;
   *new_height = nh;
+  if (new_x != NULL)
+    *new_x = dosemu_x;
+  if (new_y != NULL)
+    *new_y = dosemu_y;
 }
 
 void X_redraw_text_screen()
-- 
1.9.1
 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 16:37:11
      
     | 
| From: "Ryan C. Underwood" <ne...@ic...>
XRandR support is fully added and works properly in a multihead configuration
if the user's version is at least 1.2.  It works basically like the existing
XVidMode code and is preferred whenever it is available.  It will also properly
restore the dosemu window's position when exiting fullscreen mode.
Keyboard and mouse grabbing had to be reworked to account for multihead (e.g.,
fullscreen DOS window on one output but with the ability to use applications on
a different output).
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 configure.ac            |  17 +++
 src/include/config.h.in |   3 +
 src/plugin/X/X.c        | 275 ++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 252 insertions(+), 43 deletions(-)
diff --git a/configure.ac b/configure.ac
index a5b4df9..f444b31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,6 +376,20 @@ if test "$have_x" = "yes" ; then
                  [#include <X11/Xlib.h>])
     fi
 
+    AC_ARG_ENABLE(xrandr,
+              {  --disable-xrandr        do NOT use the XRandR extension])
+    if test "$enable_xrandr" != "no" ; then
+      AC_CHECK_LIB(Xrandr, XRRQueryVersion, enable_xrandr="yes", enable_xrandr="no")
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               AC_MSG_NOTICE(Compiling without the XRandR extension)
+    else
+         AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+     [AC_DEFINE(HAVE_XRANDR,1) X_LIBS="-lXrandr $X_LIBS"],
+                 AC_MSG_NOTICE(Compiling without the XRandR extension),
+                 [#include <X11/Xlib.h>])
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -768,6 +782,9 @@ AH_TEMPLATE([HAVE_MITSHM],
 AH_TEMPLATE([HAVE_XVIDMODE],
 [ Define this if you want to use the XF86 video mode extension ])
 
+AH_TEMPLATE([HAVE_XRANDR],
+[ Define this if you want to use the XRandR extension ])
+
 AH_TEMPLATE([ASPI_SUPPORT],
 [ Define this for ASPI (generic SCSI) support ])
 
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 6ef8763..7cf2248 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -134,6 +134,9 @@ EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MID
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define this if you want to use the XRandR extension */
+#undef HAVE_XRANDR
+
 /* Define this if you want to use the XF86 video mode extension */
 #undef HAVE_XVIDMODE
 
diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c
index 8e188c8..4a22b0f 100644
--- a/src/plugin/X/X.c
+++ b/src/plugin/X/X.c
@@ -235,6 +235,10 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include "emu.h"
 #include "timers.h"
 #include "bios.h"
@@ -320,6 +324,13 @@ static int modecount;
 static XF86VidModeModeInfo **vidmode_modes;
 #endif
 
+#ifdef HAVE_XRANDR
+static int xrandr_ok = 0;
+static RRMode xrandr_win_mode = None;
+static RRCrtc xrandr_win_crtc = None;
+static int xrandr_win_xpos, xrandr_win_ypos;
+#endif
+
 Display *display;		/* used in plugin/?/keyb_X_keycode.c */
 static int screen;
 static Visual *visual;
@@ -369,7 +380,7 @@ static unsigned ximage_bits_per_pixel;
 static unsigned ximage_mode;
 static vga_emu_update_type veut;
 
-static int grab_active = 0, kbd_grab_active = 0;
+static int grab_active = 0, kbd_grab_active = 0, force_kbd_grab = 0;
 #if CONFIG_X_MOUSE
 static char *grab_keystring = "Home";
 static KeySym grab_keysym = NoSymbol;
@@ -402,6 +413,10 @@ static void X_dga_done(void);
 static void X_xf86vm_init(void);
 static void X_xf86vm_done(void);
 #endif
+#ifdef HAVE_XRANDR
+static void X_randr_init(void);
+static void X_randr_done(void);
+#endif
 
 static void X_keymap_init(void);
 
@@ -432,7 +447,7 @@ static void resize_ximage(unsigned, unsigned);
 static int X_set_videomode(int, int, int);
 static void X_resize_text_screen(void);
 static void toggle_fullscreen_mode(int);
-static void X_vidmode(int w, int h, int *new_width, int *new_height);
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height);
 static void lock_window_size(unsigned wx_res, unsigned wy_res);
 
 /* screen update/redraw functions */
@@ -447,6 +462,7 @@ static Cursor create_invisible_cursor(void);
 /* text mode cursor manipulation stuff */
 static void X_update_cursor(void);
 
+static void toggle_kbd_grab(void);
 #if CONFIG_X_MOUSE
 /* mouse related code */
 static void set_mouse_position(int, int);
@@ -593,6 +609,10 @@ int X_init()
   X_xf86vm_init();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_init();
+#endif
+
   /* see if we find out something useful about our X server... -- sw */
   X_keymap_init();
 
@@ -806,6 +826,10 @@ void X_close()
   X_xf86vm_done();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_done();
+#endif
+
   X_load_text_font(display, 0, drawwindow, NULL, NULL, NULL);
   if(our_window) {
     XDestroyWindow(display, drawwindow);
@@ -1026,12 +1050,51 @@ static void X_xf86vm_init(void)
 static void X_xf86vm_done(void)
 {
   if (mainwindow == fullscreenwindow)
-    X_vidmode(-1, -1, &w_x_res, &w_y_res);
+    X_vidmode(-1, -1, NULL, NULL, &w_x_res, &w_y_res);
   xf86vm_ok = 0;
 }
 
 #endif
 
+#ifdef HAVE_XRANDR
+static void X_randr_init(void)
+{
+  int param1, param2;
+  if (XRRQueryExtension(display, ¶m1, ¶m2) &&
+      XRRQueryVersion(display, ¶m1, ¶m2))
+  {
+    X_printf("X: RandR Extension version %d.%d\n", param1, param2);
+    if (param1 <= 1 && param2 < 2) {
+      X_printf("X: RandR version doesn't support stretched desktop or multihead!\n");
+      /* continue anyway, as it should work for single head */
+    }
+    xrandr_ok = 1;
+  }
+}
+
+static void X_randr_exit_fullscreen(void)
+{
+  if (xrandr_win_crtc != None && xrandr_win_mode != None) {
+    X_printf("X: RandR restoring old mode %d crtc %d\n", (int)xrandr_win_mode, (int)xrandr_win_crtc);
+    XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+    XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, xrandr_win_crtc);
+    XRRSetCrtcConfig(display, sr, xrandr_win_crtc, CurrentTime, ci->x, ci->y, xrandr_win_mode, ci->rotation, ci->outputs, ci->noutput);
+    XRRFreeCrtcInfo(ci);
+    XRRFreeScreenResources(sr);
+    xrandr_win_crtc = xrandr_win_mode = None;
+  }
+}
+
+static void X_randr_done(void)
+{
+  if (mainwindow == fullscreenwindow) {
+    X_printf("X: RandR leaving fullscreen mode\n");
+    X_randr_exit_fullscreen();
+  }
+  xrandr_ok = 0;
+}
+#endif /* HAVE_XRANDR */
+
 /*
  * Handle 'auto'-entries in dosemu.conf, namely
  * $_X_keycode & $_layout
@@ -1229,15 +1292,10 @@ static void toggle_kbd_grab(void)
 {
   if(kbd_grab_active ^= 1) {
     X_printf("X: keyboard grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-    }
-  }
-  else {
+    XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+  } else {
     X_printf("X: keyboard grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabKeyboard(display, CurrentTime);
-    }
+    XUngrabKeyboard(display, CurrentTime);
   }
   X_change_config(CHG_TITLE, NULL);
 }
@@ -1247,19 +1305,15 @@ static void toggle_mouse_grab(void)
   if(grab_active ^= 1) {
     config.mouse.use_absolute = 0;
     X_printf("X: mouse grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                   GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
-    }
+    XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(1);
   }
   else {
     config.mouse.use_absolute = 1;
     X_printf("X: mouse grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabPointer(display, CurrentTime);
-    }
+    XUngrabPointer(display, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_sync_coords(mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(0);
@@ -1338,7 +1392,7 @@ static void X_wait_unmapped(Window win)
 
 static void toggle_fullscreen_mode(int init)
 {
-  int resize_height, resize_width;
+  int reloc_x, reloc_y, resize_height, resize_width;
 
   if (!init) {
     XUnmapWindow(display, mainwindow);
@@ -1351,15 +1405,12 @@ static void toggle_fullscreen_mode(int init)
     toggling_fullscreen = 2;
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
-    if (!grab_active) {
-      toggle_mouse_grab();
-      force_grab = 1;
-    }
-    X_vidmode(x_res, y_res, &resize_width, &resize_height);
+    X_vidmode(x_res, y_res, &reloc_x, &reloc_y, &resize_width, &resize_height);
     mainwindow = fullscreenwindow;
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     } else {
       shift_x = (resize_width - w_x_res) / 2;
       shift_y = (resize_height - w_y_res) / 2;
@@ -1368,30 +1419,35 @@ static void toggle_fullscreen_mode(int init)
     XMapWindow(display, mainwindow);
     XRaiseWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, shift_x, shift_y);
-    XGrabPointer(display, drawwindow, True,
-                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                 GrabModeAsync, GrabModeAsync, drawwindow,  None,
-                 CurrentTime);
-    XGrabKeyboard(display, drawwindow, True, GrabModeAsync,
-                  GrabModeAsync, CurrentTime);
+    if (!grab_active) {
+      toggle_mouse_grab();
+      force_grab = 1;
+    }
+    if (!kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 1;
+    }
   } else {
     X_printf("X: entering windowed mode!\n");
     w_x_res = saved_w_x_res;
     w_y_res = saved_w_y_res;
-    XUngrabKeyboard(display, CurrentTime);
-    XUngrabPointer(display, CurrentTime);
     mainwindow = normalwindow;
-    X_vidmode(-1, -1, &resize_width, &resize_height);
+    X_vidmode(-1, -1, &reloc_x, &reloc_y, &resize_width, &resize_height);
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating dosemu window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     }
     XMapWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, 0, 0);
     if (force_grab && grab_active) {
       toggle_mouse_grab();
+      force_grab = 0;
+    }
+    if (force_kbd_grab && kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 0;
     }
-    force_grab = 0;
   }
   if(vga.mode_class == TEXT && !use_bitmap_font) {
     X_resize_text_screen();
@@ -1550,6 +1606,7 @@ static void X_handle_events(void)
               toggle_mouse_grab();
               break;
             } else if (keysym == XK_k) {
+              force_kbd_grab = 0;
               toggle_kbd_grab();
               break;
             } else if (keysym == XK_f) {
@@ -1652,6 +1709,12 @@ static void X_handle_events(void)
 	    }
 	    set_mouse_buttons(e.xcrossing.state);
 	    mouse_really_left_window = 0;
+	    /* Grab keyboard if fullscreen (i.e., entering window from another
+	     * CRTC in a multihead system.  Otherwise we can't type.*/
+	    if (mainwindow == fullscreenwindow && !kbd_grab_active) {
+	      toggle_kbd_grab();
+	      force_kbd_grab = 1;
+	    }
           }
 	  break;
 
@@ -1666,6 +1729,12 @@ static void X_handle_events(void)
             X_printf("X: bogus LeaveNotify event\n");
             mouse_really_left_window = 0;
           }
+	  /* Release keyboard if fullscreen, mouse leaves window, and the
+	   * current grab had been forced by dosemu. */
+	  if (mainwindow == fullscreenwindow && kbd_grab_active && !force_kbd_grab) {
+	    toggle_kbd_grab();
+	    force_kbd_grab = 0;
+	  }
 	  break;
 
         case ConfigureNotify:
@@ -2066,7 +2135,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   sh.width = sh.min_width = sh.max_width = wx_res;
   sh.height = sh.min_height = sh.max_height = wy_res;
 
-  sh.flags = PSize  | PMinSize | PMaxSize;
+  sh.flags = PPosition | PSize | PMinSize | PMaxSize;
   if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect;
   if (use_bitmap_font) {
     sh.flags |= PResizeInc;
@@ -2086,7 +2155,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   x_fill = w_x_res;
   y_fill = w_y_res;
   if (mainwindow == fullscreenwindow)
-    X_vidmode(x_res, y_res, &x_fill, &y_fill);
+    X_vidmode(x_res, y_res, NULL, NULL, &x_fill, &y_fill);
 
   XResizeWindow(display, mainwindow, x_fill+1, y_fill+1);
 
@@ -2206,8 +2275,9 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
     lock_window_size(w_x_res, w_y_res);
+    /* lock_window_size() already did this, but there must be a reason ... */
     if(mainwindow == fullscreenwindow) {
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
     if (!use_bitmap_font) {
       w_x_res = saved_w_x_res;
@@ -2229,7 +2299,7 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     if(mainwindow == fullscreenwindow) {
       saved_w_x_res = w_x_res;
       saved_w_y_res = w_y_res;
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
 
     create_ximage();
@@ -2319,13 +2389,128 @@ void X_resize_text_screen()
 /*
  * Change to requested video mode or the closest greater one.
  */
-static void X_vidmode(int w, int h, int *new_width, int *new_height)
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height)
 {
   int nw, nh, mx, my, shift_x, shift_y;
 
   nw = DisplayWidth(display, screen);
   nh = DisplayHeight(display, screen);
 
+  int dosemu_x = -1, dosemu_y = -1;
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, rootwindow, &attr)) {
+    X_printf("X: X_vidmode: root window size (%d,%d)\n",
+        attr.width, attr.height);
+
+    Window child;
+    if (XTranslateCoordinates(display, normalwindow, rootwindow, 0, 0, &dosemu_x, &dosemu_y, &child)
+        && XGetWindowAttributes(display, normalwindow, &attr)) {
+      X_printf("X: X_vidmode: dosemu window loc (%d,%d) size (%d,%d)\n",
+          dosemu_x, dosemu_y, attr.width, attr.height);
+    }
+  }
+
+#ifdef HAVE_XRANDR
+  if (xrandr_ok) {
+    if (w == -1 && h == -1) {
+      /* Return to window. */
+      X_printf("X: RandR leaving fullscreen mode\n");
+      X_randr_exit_fullscreen();
+			dosemu_x = xrandr_win_xpos;
+			dosemu_y = xrandr_win_ypos;
+    } else if (mainwindow != fullscreenwindow) {
+      X_printf("X: RandR entering fullscreen mode\n");
+      /* Find which CRTC 'window' dosemu's upper left corner is within. */
+      XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+      RRCrtc crtc = None;
+			int i;
+      for (i = 0; i < sr->ncrtc; i++) {
+        XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, sr->crtcs[i]);
+        if (ci->mode == None) {
+          /* crtc disabled, try another */
+          XRRFreeCrtcInfo(ci);
+          continue;
+        }
+        X_printf("X: RandR considering CRTC (%d+%d,%d+%d)\n", ci->x, ci->width, ci->y, ci->height);
+        if (dosemu_x >= ci->x && dosemu_x < ci->x + ci->width &&
+            dosemu_y >= ci->y && dosemu_y < ci->y + ci->height)
+        {
+          X_printf("X: RandR using this CRTC\n");
+          crtc = sr->crtcs[i];
+          XRRFreeCrtcInfo(ci);
+          break;
+        }
+        XRRFreeCrtcInfo(ci);
+      }
+      if (crtc == None) {
+        error("X: RandR found no suitable CRTC!\n");
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, crtc);
+
+      /* XXX: Use the first CRTC output always.  In what display configuration
+       * could this break? */
+      int output_idx = 0;
+      XRROutputInfo *oi = XRRGetOutputInfo(display, sr, ci->outputs[output_idx]);
+
+      /* Find the best mode supported by this CRTC by first finding the
+       * closest fit that is at least as large as the DOS screen, then the
+       * best refresh rate at that size.  To do this we have to find every mode
+       * available in the output, then search the screen modes for its ID. */
+      int mode_id = -1;
+      int best_rate = 0;
+      for (i = 0; i < oi->nmode; i++) {
+        RRMode output_mode = oi->modes[i];
+				int j;
+        for (j = 0; j < sr->nmode; j++) {
+          const XRRModeInfo *mi = &sr->modes[j];
+          if (mi->id != output_mode)
+            continue;
+          int width = mi->width;
+          int height = mi->height;
+          X_printf("X: RandR considering mode (%d,%d)\n", width, height);
+          if (width >= w && height >= h && width <= nw && height <= nh) {
+            if (width != nw || height != nh)
+              best_rate = 0; /* geometry changed, start over rate search */
+            nw = width;
+            nh = height;
+            int rate = mi->dotClock / (mi->hTotal * mi->vTotal);
+            if (rate > best_rate) {
+              best_rate = rate;
+              mode_id = mi->id;
+            }
+          }
+        }
+      }
+      if (mode_id == -1) {
+        error("X: RandR found no suitable mode for CRTC output %d!\n", output_idx);
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRFreeOutputInfo(oi);
+
+      /* Change to fullscreen; save window config first. */
+      X_printf("X: RandR mode asking for (%d,%d); setting %dx%d@%d mode %d\n", w, h, nw, nh, best_rate, mode_id);
+      X_printf("X: RandR saving old mode %d crtc %d\n", (int)ci->mode, (int)crtc);
+      xrandr_win_mode = ci->mode;
+      xrandr_win_crtc = crtc;
+			xrandr_win_xpos = dosemu_x;
+			xrandr_win_ypos = dosemu_y;
+			/* Position window at (0,0) on *this* CRTC. */
+			dosemu_x = ci->x;
+			dosemu_y = ci->y;
+      XRRSetCrtcConfig(display, sr, crtc, CurrentTime, ci->x, ci->y, mode_id, ci->rotation, ci->outputs, ci->noutput);
+      XRRFreeCrtcInfo(ci);
+      XRRFreeScreenResources(sr);
+      /* Callers always set this themselves, but anyway... */
+      mainwindow = fullscreenwindow;
+    }
+  } else /* Only attempt VidMode or non-modechange fullscreen if RandR is disabled. */
+#endif /* HAVE_XRANDR */
+
 #ifdef HAVE_XVIDMODE
   if (xf86vm_ok) {
     static XF86VidModeModeLine vidmode_modeline;
@@ -2402,6 +2587,10 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height)
     XWarpPointer(display, None, drawwindow, 0, 0, 0, 0, mx, my);
   *new_width = nw;
   *new_height = nh;
+  if (new_x != NULL)
+    *new_x = dosemu_x;
+  if (new_y != NULL)
+    *new_y = dosemu_y;
 }
 
 /*
-- 
1.9.1
 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 06:18:28
      
     | 
| From: "Ryan C. Underwood" <ne...@ic...>
XRandR support is fully added and works properly in a multihead configuration
if the user's version is at least 1.2.  It works basically like the existing
XVidMode code and is preferred whenever it is available.  It will also properly
restore the dosemu window's position when exiting fullscreen mode.
Keyboard and mouse grabbing had to be reworked to account for multihead (e.g.,
fullscreen DOS window on one output but with the ability to use applications on
a different output).
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 configure.ac            |  17 +++
 src/include/config.h.in |   3 +
 src/plugin/X/X.c        | 275 ++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 252 insertions(+), 43 deletions(-)
diff --git a/configure.ac b/configure.ac
index a5b4df9..f444b31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,6 +376,20 @@ if test "$have_x" = "yes" ; then
                  [#include <X11/Xlib.h>])
     fi
 
+    AC_ARG_ENABLE(xrandr,
+              {  --disable-xrandr        do NOT use the XRandR extension])
+    if test "$enable_xrandr" != "no" ; then
+      AC_CHECK_LIB(Xrandr, XRRQueryVersion, enable_xrandr="yes", enable_xrandr="no")
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               AC_MSG_NOTICE(Compiling without the XRandR extension)
+    else
+         AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+     [AC_DEFINE(HAVE_XRANDR,1) X_LIBS="-lXrandr $X_LIBS"],
+                 AC_MSG_NOTICE(Compiling without the XRandR extension),
+                 [#include <X11/Xlib.h>])
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -768,6 +782,9 @@ AH_TEMPLATE([HAVE_MITSHM],
 AH_TEMPLATE([HAVE_XVIDMODE],
 [ Define this if you want to use the XF86 video mode extension ])
 
+AH_TEMPLATE([HAVE_XRANDR],
+[ Define this if you want to use the XRandR extension ])
+
 AH_TEMPLATE([ASPI_SUPPORT],
 [ Define this for ASPI (generic SCSI) support ])
 
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 6ef8763..7cf2248 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -134,6 +134,9 @@ EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MID
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define this if you want to use the XRandR extension */
+#undef HAVE_XRANDR
+
 /* Define this if you want to use the XF86 video mode extension */
 #undef HAVE_XVIDMODE
 
diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c
index 8e188c8..4a22b0f 100644
--- a/src/plugin/X/X.c
+++ b/src/plugin/X/X.c
@@ -235,6 +235,10 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include "emu.h"
 #include "timers.h"
 #include "bios.h"
@@ -320,6 +324,13 @@ static int modecount;
 static XF86VidModeModeInfo **vidmode_modes;
 #endif
 
+#ifdef HAVE_XRANDR
+static int xrandr_ok = 0;
+static RRMode xrandr_win_mode = None;
+static RRCrtc xrandr_win_crtc = None;
+static int xrandr_win_xpos, xrandr_win_ypos;
+#endif
+
 Display *display;		/* used in plugin/?/keyb_X_keycode.c */
 static int screen;
 static Visual *visual;
@@ -369,7 +380,7 @@ static unsigned ximage_bits_per_pixel;
 static unsigned ximage_mode;
 static vga_emu_update_type veut;
 
-static int grab_active = 0, kbd_grab_active = 0;
+static int grab_active = 0, kbd_grab_active = 0, force_kbd_grab = 0;
 #if CONFIG_X_MOUSE
 static char *grab_keystring = "Home";
 static KeySym grab_keysym = NoSymbol;
@@ -402,6 +413,10 @@ static void X_dga_done(void);
 static void X_xf86vm_init(void);
 static void X_xf86vm_done(void);
 #endif
+#ifdef HAVE_XRANDR
+static void X_randr_init(void);
+static void X_randr_done(void);
+#endif
 
 static void X_keymap_init(void);
 
@@ -432,7 +447,7 @@ static void resize_ximage(unsigned, unsigned);
 static int X_set_videomode(int, int, int);
 static void X_resize_text_screen(void);
 static void toggle_fullscreen_mode(int);
-static void X_vidmode(int w, int h, int *new_width, int *new_height);
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height);
 static void lock_window_size(unsigned wx_res, unsigned wy_res);
 
 /* screen update/redraw functions */
@@ -447,6 +462,7 @@ static Cursor create_invisible_cursor(void);
 /* text mode cursor manipulation stuff */
 static void X_update_cursor(void);
 
+static void toggle_kbd_grab(void);
 #if CONFIG_X_MOUSE
 /* mouse related code */
 static void set_mouse_position(int, int);
@@ -593,6 +609,10 @@ int X_init()
   X_xf86vm_init();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_init();
+#endif
+
   /* see if we find out something useful about our X server... -- sw */
   X_keymap_init();
 
@@ -806,6 +826,10 @@ void X_close()
   X_xf86vm_done();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_done();
+#endif
+
   X_load_text_font(display, 0, drawwindow, NULL, NULL, NULL);
   if(our_window) {
     XDestroyWindow(display, drawwindow);
@@ -1026,12 +1050,51 @@ static void X_xf86vm_init(void)
 static void X_xf86vm_done(void)
 {
   if (mainwindow == fullscreenwindow)
-    X_vidmode(-1, -1, &w_x_res, &w_y_res);
+    X_vidmode(-1, -1, NULL, NULL, &w_x_res, &w_y_res);
   xf86vm_ok = 0;
 }
 
 #endif
 
+#ifdef HAVE_XRANDR
+static void X_randr_init(void)
+{
+  int param1, param2;
+  if (XRRQueryExtension(display, ¶m1, ¶m2) &&
+      XRRQueryVersion(display, ¶m1, ¶m2))
+  {
+    X_printf("X: RandR Extension version %d.%d\n", param1, param2);
+    if (param1 <= 1 && param2 < 2) {
+      X_printf("X: RandR version doesn't support stretched desktop or multihead!\n");
+      /* continue anyway, as it should work for single head */
+    }
+    xrandr_ok = 1;
+  }
+}
+
+static void X_randr_exit_fullscreen(void)
+{
+  if (xrandr_win_crtc != None && xrandr_win_mode != None) {
+    X_printf("X: RandR restoring old mode %d crtc %d\n", (int)xrandr_win_mode, (int)xrandr_win_crtc);
+    XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+    XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, xrandr_win_crtc);
+    XRRSetCrtcConfig(display, sr, xrandr_win_crtc, CurrentTime, ci->x, ci->y, xrandr_win_mode, ci->rotation, ci->outputs, ci->noutput);
+    XRRFreeCrtcInfo(ci);
+    XRRFreeScreenResources(sr);
+    xrandr_win_crtc = xrandr_win_mode = None;
+  }
+}
+
+static void X_randr_done(void)
+{
+  if (mainwindow == fullscreenwindow) {
+    X_printf("X: RandR leaving fullscreen mode\n");
+    X_randr_exit_fullscreen();
+  }
+  xrandr_ok = 0;
+}
+#endif /* HAVE_XRANDR */
+
 /*
  * Handle 'auto'-entries in dosemu.conf, namely
  * $_X_keycode & $_layout
@@ -1229,15 +1292,10 @@ static void toggle_kbd_grab(void)
 {
   if(kbd_grab_active ^= 1) {
     X_printf("X: keyboard grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-    }
-  }
-  else {
+    XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+  } else {
     X_printf("X: keyboard grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabKeyboard(display, CurrentTime);
-    }
+    XUngrabKeyboard(display, CurrentTime);
   }
   X_change_config(CHG_TITLE, NULL);
 }
@@ -1247,19 +1305,15 @@ static void toggle_mouse_grab(void)
   if(grab_active ^= 1) {
     config.mouse.use_absolute = 0;
     X_printf("X: mouse grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                   GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
-    }
+    XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(1);
   }
   else {
     config.mouse.use_absolute = 1;
     X_printf("X: mouse grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabPointer(display, CurrentTime);
-    }
+    XUngrabPointer(display, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_sync_coords(mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(0);
@@ -1338,7 +1392,7 @@ static void X_wait_unmapped(Window win)
 
 static void toggle_fullscreen_mode(int init)
 {
-  int resize_height, resize_width;
+  int reloc_x, reloc_y, resize_height, resize_width;
 
   if (!init) {
     XUnmapWindow(display, mainwindow);
@@ -1351,15 +1405,12 @@ static void toggle_fullscreen_mode(int init)
     toggling_fullscreen = 2;
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
-    if (!grab_active) {
-      toggle_mouse_grab();
-      force_grab = 1;
-    }
-    X_vidmode(x_res, y_res, &resize_width, &resize_height);
+    X_vidmode(x_res, y_res, &reloc_x, &reloc_y, &resize_width, &resize_height);
     mainwindow = fullscreenwindow;
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     } else {
       shift_x = (resize_width - w_x_res) / 2;
       shift_y = (resize_height - w_y_res) / 2;
@@ -1368,30 +1419,35 @@ static void toggle_fullscreen_mode(int init)
     XMapWindow(display, mainwindow);
     XRaiseWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, shift_x, shift_y);
-    XGrabPointer(display, drawwindow, True,
-                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                 GrabModeAsync, GrabModeAsync, drawwindow,  None,
-                 CurrentTime);
-    XGrabKeyboard(display, drawwindow, True, GrabModeAsync,
-                  GrabModeAsync, CurrentTime);
+    if (!grab_active) {
+      toggle_mouse_grab();
+      force_grab = 1;
+    }
+    if (!kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 1;
+    }
   } else {
     X_printf("X: entering windowed mode!\n");
     w_x_res = saved_w_x_res;
     w_y_res = saved_w_y_res;
-    XUngrabKeyboard(display, CurrentTime);
-    XUngrabPointer(display, CurrentTime);
     mainwindow = normalwindow;
-    X_vidmode(-1, -1, &resize_width, &resize_height);
+    X_vidmode(-1, -1, &reloc_x, &reloc_y, &resize_width, &resize_height);
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating dosemu window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     }
     XMapWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, 0, 0);
     if (force_grab && grab_active) {
       toggle_mouse_grab();
+      force_grab = 0;
+    }
+    if (force_kbd_grab && kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 0;
     }
-    force_grab = 0;
   }
   if(vga.mode_class == TEXT && !use_bitmap_font) {
     X_resize_text_screen();
@@ -1550,6 +1606,7 @@ static void X_handle_events(void)
               toggle_mouse_grab();
               break;
             } else if (keysym == XK_k) {
+              force_kbd_grab = 0;
               toggle_kbd_grab();
               break;
             } else if (keysym == XK_f) {
@@ -1652,6 +1709,12 @@ static void X_handle_events(void)
 	    }
 	    set_mouse_buttons(e.xcrossing.state);
 	    mouse_really_left_window = 0;
+	    /* Grab keyboard if fullscreen (i.e., entering window from another
+	     * CRTC in a multihead system.  Otherwise we can't type.*/
+	    if (mainwindow == fullscreenwindow && !kbd_grab_active) {
+	      toggle_kbd_grab();
+	      force_kbd_grab = 1;
+	    }
           }
 	  break;
 
@@ -1666,6 +1729,12 @@ static void X_handle_events(void)
             X_printf("X: bogus LeaveNotify event\n");
             mouse_really_left_window = 0;
           }
+	  /* Release keyboard if fullscreen, mouse leaves window, and the
+	   * current grab had been forced by dosemu. */
+	  if (mainwindow == fullscreenwindow && kbd_grab_active && !force_kbd_grab) {
+	    toggle_kbd_grab();
+	    force_kbd_grab = 0;
+	  }
 	  break;
 
         case ConfigureNotify:
@@ -2066,7 +2135,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   sh.width = sh.min_width = sh.max_width = wx_res;
   sh.height = sh.min_height = sh.max_height = wy_res;
 
-  sh.flags = PSize  | PMinSize | PMaxSize;
+  sh.flags = PPosition | PSize | PMinSize | PMaxSize;
   if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect;
   if (use_bitmap_font) {
     sh.flags |= PResizeInc;
@@ -2086,7 +2155,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   x_fill = w_x_res;
   y_fill = w_y_res;
   if (mainwindow == fullscreenwindow)
-    X_vidmode(x_res, y_res, &x_fill, &y_fill);
+    X_vidmode(x_res, y_res, NULL, NULL, &x_fill, &y_fill);
 
   XResizeWindow(display, mainwindow, x_fill+1, y_fill+1);
 
@@ -2206,8 +2275,9 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
     lock_window_size(w_x_res, w_y_res);
+    /* lock_window_size() already did this, but there must be a reason ... */
     if(mainwindow == fullscreenwindow) {
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
     if (!use_bitmap_font) {
       w_x_res = saved_w_x_res;
@@ -2229,7 +2299,7 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     if(mainwindow == fullscreenwindow) {
       saved_w_x_res = w_x_res;
       saved_w_y_res = w_y_res;
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
 
     create_ximage();
@@ -2319,13 +2389,128 @@ void X_resize_text_screen()
 /*
  * Change to requested video mode or the closest greater one.
  */
-static void X_vidmode(int w, int h, int *new_width, int *new_height)
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height)
 {
   int nw, nh, mx, my, shift_x, shift_y;
 
   nw = DisplayWidth(display, screen);
   nh = DisplayHeight(display, screen);
 
+  int dosemu_x = -1, dosemu_y = -1;
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, rootwindow, &attr)) {
+    X_printf("X: X_vidmode: root window size (%d,%d)\n",
+        attr.width, attr.height);
+
+    Window child;
+    if (XTranslateCoordinates(display, normalwindow, rootwindow, 0, 0, &dosemu_x, &dosemu_y, &child)
+        && XGetWindowAttributes(display, normalwindow, &attr)) {
+      X_printf("X: X_vidmode: dosemu window loc (%d,%d) size (%d,%d)\n",
+          dosemu_x, dosemu_y, attr.width, attr.height);
+    }
+  }
+
+#ifdef HAVE_XRANDR
+  if (xrandr_ok) {
+    if (w == -1 && h == -1) {
+      /* Return to window. */
+      X_printf("X: RandR leaving fullscreen mode\n");
+      X_randr_exit_fullscreen();
+			dosemu_x = xrandr_win_xpos;
+			dosemu_y = xrandr_win_ypos;
+    } else if (mainwindow != fullscreenwindow) {
+      X_printf("X: RandR entering fullscreen mode\n");
+      /* Find which CRTC 'window' dosemu's upper left corner is within. */
+      XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+      RRCrtc crtc = None;
+			int i;
+      for (i = 0; i < sr->ncrtc; i++) {
+        XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, sr->crtcs[i]);
+        if (ci->mode == None) {
+          /* crtc disabled, try another */
+          XRRFreeCrtcInfo(ci);
+          continue;
+        }
+        X_printf("X: RandR considering CRTC (%d+%d,%d+%d)\n", ci->x, ci->width, ci->y, ci->height);
+        if (dosemu_x >= ci->x && dosemu_x < ci->x + ci->width &&
+            dosemu_y >= ci->y && dosemu_y < ci->y + ci->height)
+        {
+          X_printf("X: RandR using this CRTC\n");
+          crtc = sr->crtcs[i];
+          XRRFreeCrtcInfo(ci);
+          break;
+        }
+        XRRFreeCrtcInfo(ci);
+      }
+      if (crtc == None) {
+        error("X: RandR found no suitable CRTC!\n");
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, crtc);
+
+      /* XXX: Use the first CRTC output always.  In what display configuration
+       * could this break? */
+      int output_idx = 0;
+      XRROutputInfo *oi = XRRGetOutputInfo(display, sr, ci->outputs[output_idx]);
+
+      /* Find the best mode supported by this CRTC by first finding the
+       * closest fit that is at least as large as the DOS screen, then the
+       * best refresh rate at that size.  To do this we have to find every mode
+       * available in the output, then search the screen modes for its ID. */
+      int mode_id = -1;
+      int best_rate = 0;
+      for (i = 0; i < oi->nmode; i++) {
+        RRMode output_mode = oi->modes[i];
+				int j;
+        for (j = 0; j < sr->nmode; j++) {
+          const XRRModeInfo *mi = &sr->modes[j];
+          if (mi->id != output_mode)
+            continue;
+          int width = mi->width;
+          int height = mi->height;
+          X_printf("X: RandR considering mode (%d,%d)\n", width, height);
+          if (width >= w && height >= h && width <= nw && height <= nh) {
+            if (width != nw || height != nh)
+              best_rate = 0; /* geometry changed, start over rate search */
+            nw = width;
+            nh = height;
+            int rate = mi->dotClock / (mi->hTotal * mi->vTotal);
+            if (rate > best_rate) {
+              best_rate = rate;
+              mode_id = mi->id;
+            }
+          }
+        }
+      }
+      if (mode_id == -1) {
+        error("X: RandR found no suitable mode for CRTC output %d!\n", output_idx);
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRFreeOutputInfo(oi);
+
+      /* Change to fullscreen; save window config first. */
+      X_printf("X: RandR mode asking for (%d,%d); setting %dx%d@%d mode %d\n", w, h, nw, nh, best_rate, mode_id);
+      X_printf("X: RandR saving old mode %d crtc %d\n", (int)ci->mode, (int)crtc);
+      xrandr_win_mode = ci->mode;
+      xrandr_win_crtc = crtc;
+			xrandr_win_xpos = dosemu_x;
+			xrandr_win_ypos = dosemu_y;
+			/* Position window at (0,0) on *this* CRTC. */
+			dosemu_x = ci->x;
+			dosemu_y = ci->y;
+      XRRSetCrtcConfig(display, sr, crtc, CurrentTime, ci->x, ci->y, mode_id, ci->rotation, ci->outputs, ci->noutput);
+      XRRFreeCrtcInfo(ci);
+      XRRFreeScreenResources(sr);
+      /* Callers always set this themselves, but anyway... */
+      mainwindow = fullscreenwindow;
+    }
+  } else /* Only attempt VidMode or non-modechange fullscreen if RandR is disabled. */
+#endif /* HAVE_XRANDR */
+
 #ifdef HAVE_XVIDMODE
   if (xf86vm_ok) {
     static XF86VidModeModeLine vidmode_modeline;
@@ -2402,6 +2587,10 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height)
     XWarpPointer(display, None, drawwindow, 0, 0, 0, 0, mx, my);
   *new_width = nw;
   *new_height = nh;
+  if (new_x != NULL)
+    *new_x = dosemu_x;
+  if (new_y != NULL)
+    *new_y = dosemu_y;
 }
 
 /*
-- 
1.9.1
 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 06:15:33
      
     | 
| From: "Ryan C. Underwood" <ne...@ic...>
XRandR support is fully added and works properly in a multihead configuration
if the user's version is at least 1.2.  It works basically like the existing
XVidMode code and is preferred whenever it is available.  It will also properly
restore the dosemu window's position when exiting fullscreen mode.
Keyboard and mouse grabbing had to be reworked to account for multihead (e.g.,
fullscreen DOS window on one output but with the ability to use applications on
a different output).
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 configure.ac            |  17 +++
 src/include/config.h.in |   3 +
 src/plugin/X/X.c        | 275 ++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 252 insertions(+), 43 deletions(-)
diff --git a/configure.ac b/configure.ac
index a5b4df9..f444b31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,6 +376,20 @@ if test "$have_x" = "yes" ; then
                  [#include <X11/Xlib.h>])
     fi
 
+    AC_ARG_ENABLE(xrandr,
+              {  --disable-xrandr        do NOT use the XRandR extension])
+    if test "$enable_xrandr" != "no" ; then
+      AC_CHECK_LIB(Xrandr, XRRQueryVersion, enable_xrandr="yes", enable_xrandr="no")
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               AC_MSG_NOTICE(Compiling without the XRandR extension)
+    else
+         AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+     [AC_DEFINE(HAVE_XRANDR,1) X_LIBS="-lXrandr $X_LIBS"],
+                 AC_MSG_NOTICE(Compiling without the XRandR extension),
+                 [#include <X11/Xlib.h>])
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -768,6 +782,9 @@ AH_TEMPLATE([HAVE_MITSHM],
 AH_TEMPLATE([HAVE_XVIDMODE],
 [ Define this if you want to use the XF86 video mode extension ])
 
+AH_TEMPLATE([HAVE_XRANDR],
+[ Define this if you want to use the XRandR extension ])
+
 AH_TEMPLATE([ASPI_SUPPORT],
 [ Define this for ASPI (generic SCSI) support ])
 
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 6ef8763..7cf2248 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -134,6 +134,9 @@ EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MID
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define this if you want to use the XRandR extension */
+#undef HAVE_XRANDR
+
 /* Define this if you want to use the XF86 video mode extension */
 #undef HAVE_XVIDMODE
 
diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c
index 8e188c8..4a22b0f 100644
--- a/src/plugin/X/X.c
+++ b/src/plugin/X/X.c
@@ -235,6 +235,10 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include "emu.h"
 #include "timers.h"
 #include "bios.h"
@@ -320,6 +324,13 @@ static int modecount;
 static XF86VidModeModeInfo **vidmode_modes;
 #endif
 
+#ifdef HAVE_XRANDR
+static int xrandr_ok = 0;
+static RRMode xrandr_win_mode = None;
+static RRCrtc xrandr_win_crtc = None;
+static int xrandr_win_xpos, xrandr_win_ypos;
+#endif
+
 Display *display;		/* used in plugin/?/keyb_X_keycode.c */
 static int screen;
 static Visual *visual;
@@ -369,7 +380,7 @@ static unsigned ximage_bits_per_pixel;
 static unsigned ximage_mode;
 static vga_emu_update_type veut;
 
-static int grab_active = 0, kbd_grab_active = 0;
+static int grab_active = 0, kbd_grab_active = 0, force_kbd_grab = 0;
 #if CONFIG_X_MOUSE
 static char *grab_keystring = "Home";
 static KeySym grab_keysym = NoSymbol;
@@ -402,6 +413,10 @@ static void X_dga_done(void);
 static void X_xf86vm_init(void);
 static void X_xf86vm_done(void);
 #endif
+#ifdef HAVE_XRANDR
+static void X_randr_init(void);
+static void X_randr_done(void);
+#endif
 
 static void X_keymap_init(void);
 
@@ -432,7 +447,7 @@ static void resize_ximage(unsigned, unsigned);
 static int X_set_videomode(int, int, int);
 static void X_resize_text_screen(void);
 static void toggle_fullscreen_mode(int);
-static void X_vidmode(int w, int h, int *new_width, int *new_height);
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height);
 static void lock_window_size(unsigned wx_res, unsigned wy_res);
 
 /* screen update/redraw functions */
@@ -447,6 +462,7 @@ static Cursor create_invisible_cursor(void);
 /* text mode cursor manipulation stuff */
 static void X_update_cursor(void);
 
+static void toggle_kbd_grab(void);
 #if CONFIG_X_MOUSE
 /* mouse related code */
 static void set_mouse_position(int, int);
@@ -593,6 +609,10 @@ int X_init()
   X_xf86vm_init();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_init();
+#endif
+
   /* see if we find out something useful about our X server... -- sw */
   X_keymap_init();
 
@@ -806,6 +826,10 @@ void X_close()
   X_xf86vm_done();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_done();
+#endif
+
   X_load_text_font(display, 0, drawwindow, NULL, NULL, NULL);
   if(our_window) {
     XDestroyWindow(display, drawwindow);
@@ -1026,12 +1050,51 @@ static void X_xf86vm_init(void)
 static void X_xf86vm_done(void)
 {
   if (mainwindow == fullscreenwindow)
-    X_vidmode(-1, -1, &w_x_res, &w_y_res);
+    X_vidmode(-1, -1, NULL, NULL, &w_x_res, &w_y_res);
   xf86vm_ok = 0;
 }
 
 #endif
 
+#ifdef HAVE_XRANDR
+static void X_randr_init(void)
+{
+  int param1, param2;
+  if (XRRQueryExtension(display, ¶m1, ¶m2) &&
+      XRRQueryVersion(display, ¶m1, ¶m2))
+  {
+    X_printf("X: RandR Extension version %d.%d\n", param1, param2);
+    if (param1 <= 1 && param2 < 2) {
+      X_printf("X: RandR version doesn't support stretched desktop or multihead!\n");
+      /* continue anyway, as it should work for single head */
+    }
+    xrandr_ok = 1;
+  }
+}
+
+static void X_randr_exit_fullscreen(void)
+{
+  if (xrandr_win_crtc != None && xrandr_win_mode != None) {
+    X_printf("X: RandR restoring old mode %d crtc %d\n", (int)xrandr_win_mode, (int)xrandr_win_crtc);
+    XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+    XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, xrandr_win_crtc);
+    XRRSetCrtcConfig(display, sr, xrandr_win_crtc, CurrentTime, ci->x, ci->y, xrandr_win_mode, ci->rotation, ci->outputs, ci->noutput);
+    XRRFreeCrtcInfo(ci);
+    XRRFreeScreenResources(sr);
+    xrandr_win_crtc = xrandr_win_mode = None;
+  }
+}
+
+static void X_randr_done(void)
+{
+  if (mainwindow == fullscreenwindow) {
+    X_printf("X: RandR leaving fullscreen mode\n");
+    X_randr_exit_fullscreen();
+  }
+  xrandr_ok = 0;
+}
+#endif /* HAVE_XRANDR */
+
 /*
  * Handle 'auto'-entries in dosemu.conf, namely
  * $_X_keycode & $_layout
@@ -1229,15 +1292,10 @@ static void toggle_kbd_grab(void)
 {
   if(kbd_grab_active ^= 1) {
     X_printf("X: keyboard grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-    }
-  }
-  else {
+    XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+  } else {
     X_printf("X: keyboard grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabKeyboard(display, CurrentTime);
-    }
+    XUngrabKeyboard(display, CurrentTime);
   }
   X_change_config(CHG_TITLE, NULL);
 }
@@ -1247,19 +1305,15 @@ static void toggle_mouse_grab(void)
   if(grab_active ^= 1) {
     config.mouse.use_absolute = 0;
     X_printf("X: mouse grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                   GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
-    }
+    XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(1);
   }
   else {
     config.mouse.use_absolute = 1;
     X_printf("X: mouse grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabPointer(display, CurrentTime);
-    }
+    XUngrabPointer(display, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_sync_coords(mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(0);
@@ -1338,7 +1392,7 @@ static void X_wait_unmapped(Window win)
 
 static void toggle_fullscreen_mode(int init)
 {
-  int resize_height, resize_width;
+  int reloc_x, reloc_y, resize_height, resize_width;
 
   if (!init) {
     XUnmapWindow(display, mainwindow);
@@ -1351,15 +1405,12 @@ static void toggle_fullscreen_mode(int init)
     toggling_fullscreen = 2;
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
-    if (!grab_active) {
-      toggle_mouse_grab();
-      force_grab = 1;
-    }
-    X_vidmode(x_res, y_res, &resize_width, &resize_height);
+    X_vidmode(x_res, y_res, &reloc_x, &reloc_y, &resize_width, &resize_height);
     mainwindow = fullscreenwindow;
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     } else {
       shift_x = (resize_width - w_x_res) / 2;
       shift_y = (resize_height - w_y_res) / 2;
@@ -1368,30 +1419,35 @@ static void toggle_fullscreen_mode(int init)
     XMapWindow(display, mainwindow);
     XRaiseWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, shift_x, shift_y);
-    XGrabPointer(display, drawwindow, True,
-                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                 GrabModeAsync, GrabModeAsync, drawwindow,  None,
-                 CurrentTime);
-    XGrabKeyboard(display, drawwindow, True, GrabModeAsync,
-                  GrabModeAsync, CurrentTime);
+    if (!grab_active) {
+      toggle_mouse_grab();
+      force_grab = 1;
+    }
+    if (!kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 1;
+    }
   } else {
     X_printf("X: entering windowed mode!\n");
     w_x_res = saved_w_x_res;
     w_y_res = saved_w_y_res;
-    XUngrabKeyboard(display, CurrentTime);
-    XUngrabPointer(display, CurrentTime);
     mainwindow = normalwindow;
-    X_vidmode(-1, -1, &resize_width, &resize_height);
+    X_vidmode(-1, -1, &reloc_x, &reloc_y, &resize_width, &resize_height);
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating dosemu window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     }
     XMapWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, 0, 0);
     if (force_grab && grab_active) {
       toggle_mouse_grab();
+      force_grab = 0;
+    }
+    if (force_kbd_grab && kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 0;
     }
-    force_grab = 0;
   }
   if(vga.mode_class == TEXT && !use_bitmap_font) {
     X_resize_text_screen();
@@ -1550,6 +1606,7 @@ static void X_handle_events(void)
               toggle_mouse_grab();
               break;
             } else if (keysym == XK_k) {
+              force_kbd_grab = 0;
               toggle_kbd_grab();
               break;
             } else if (keysym == XK_f) {
@@ -1652,6 +1709,12 @@ static void X_handle_events(void)
 	    }
 	    set_mouse_buttons(e.xcrossing.state);
 	    mouse_really_left_window = 0;
+	    /* Grab keyboard if fullscreen (i.e., entering window from another
+	     * CRTC in a multihead system.  Otherwise we can't type.*/
+	    if (mainwindow == fullscreenwindow && !kbd_grab_active) {
+	      toggle_kbd_grab();
+	      force_kbd_grab = 1;
+	    }
           }
 	  break;
 
@@ -1666,6 +1729,12 @@ static void X_handle_events(void)
             X_printf("X: bogus LeaveNotify event\n");
             mouse_really_left_window = 0;
           }
+	  /* Release keyboard if fullscreen, mouse leaves window, and the
+	   * current grab had been forced by dosemu. */
+	  if (mainwindow == fullscreenwindow && kbd_grab_active && !force_kbd_grab) {
+	    toggle_kbd_grab();
+	    force_kbd_grab = 0;
+	  }
 	  break;
 
         case ConfigureNotify:
@@ -2066,7 +2135,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   sh.width = sh.min_width = sh.max_width = wx_res;
   sh.height = sh.min_height = sh.max_height = wy_res;
 
-  sh.flags = PSize  | PMinSize | PMaxSize;
+  sh.flags = PPosition | PSize | PMinSize | PMaxSize;
   if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect;
   if (use_bitmap_font) {
     sh.flags |= PResizeInc;
@@ -2086,7 +2155,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   x_fill = w_x_res;
   y_fill = w_y_res;
   if (mainwindow == fullscreenwindow)
-    X_vidmode(x_res, y_res, &x_fill, &y_fill);
+    X_vidmode(x_res, y_res, NULL, NULL, &x_fill, &y_fill);
 
   XResizeWindow(display, mainwindow, x_fill+1, y_fill+1);
 
@@ -2206,8 +2275,9 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
     lock_window_size(w_x_res, w_y_res);
+    /* lock_window_size() already did this, but there must be a reason ... */
     if(mainwindow == fullscreenwindow) {
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
     if (!use_bitmap_font) {
       w_x_res = saved_w_x_res;
@@ -2229,7 +2299,7 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     if(mainwindow == fullscreenwindow) {
       saved_w_x_res = w_x_res;
       saved_w_y_res = w_y_res;
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
 
     create_ximage();
@@ -2319,13 +2389,128 @@ void X_resize_text_screen()
 /*
  * Change to requested video mode or the closest greater one.
  */
-static void X_vidmode(int w, int h, int *new_width, int *new_height)
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height)
 {
   int nw, nh, mx, my, shift_x, shift_y;
 
   nw = DisplayWidth(display, screen);
   nh = DisplayHeight(display, screen);
 
+  int dosemu_x = -1, dosemu_y = -1;
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, rootwindow, &attr)) {
+    X_printf("X: X_vidmode: root window size (%d,%d)\n",
+        attr.width, attr.height);
+
+    Window child;
+    if (XTranslateCoordinates(display, normalwindow, rootwindow, 0, 0, &dosemu_x, &dosemu_y, &child)
+        && XGetWindowAttributes(display, normalwindow, &attr)) {
+      X_printf("X: X_vidmode: dosemu window loc (%d,%d) size (%d,%d)\n",
+          dosemu_x, dosemu_y, attr.width, attr.height);
+    }
+  }
+
+#ifdef HAVE_XRANDR
+  if (xrandr_ok) {
+    if (w == -1 && h == -1) {
+      /* Return to window. */
+      X_printf("X: RandR leaving fullscreen mode\n");
+      X_randr_exit_fullscreen();
+			dosemu_x = xrandr_win_xpos;
+			dosemu_y = xrandr_win_ypos;
+    } else if (mainwindow != fullscreenwindow) {
+      X_printf("X: RandR entering fullscreen mode\n");
+      /* Find which CRTC 'window' dosemu's upper left corner is within. */
+      XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+      RRCrtc crtc = None;
+			int i;
+      for (i = 0; i < sr->ncrtc; i++) {
+        XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, sr->crtcs[i]);
+        if (ci->mode == None) {
+          /* crtc disabled, try another */
+          XRRFreeCrtcInfo(ci);
+          continue;
+        }
+        X_printf("X: RandR considering CRTC (%d+%d,%d+%d)\n", ci->x, ci->width, ci->y, ci->height);
+        if (dosemu_x >= ci->x && dosemu_x < ci->x + ci->width &&
+            dosemu_y >= ci->y && dosemu_y < ci->y + ci->height)
+        {
+          X_printf("X: RandR using this CRTC\n");
+          crtc = sr->crtcs[i];
+          XRRFreeCrtcInfo(ci);
+          break;
+        }
+        XRRFreeCrtcInfo(ci);
+      }
+      if (crtc == None) {
+        error("X: RandR found no suitable CRTC!\n");
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, crtc);
+
+      /* XXX: Use the first CRTC output always.  In what display configuration
+       * could this break? */
+      int output_idx = 0;
+      XRROutputInfo *oi = XRRGetOutputInfo(display, sr, ci->outputs[output_idx]);
+
+      /* Find the best mode supported by this CRTC by first finding the
+       * closest fit that is at least as large as the DOS screen, then the
+       * best refresh rate at that size.  To do this we have to find every mode
+       * available in the output, then search the screen modes for its ID. */
+      int mode_id = -1;
+      int best_rate = 0;
+      for (i = 0; i < oi->nmode; i++) {
+        RRMode output_mode = oi->modes[i];
+				int j;
+        for (j = 0; j < sr->nmode; j++) {
+          const XRRModeInfo *mi = &sr->modes[j];
+          if (mi->id != output_mode)
+            continue;
+          int width = mi->width;
+          int height = mi->height;
+          X_printf("X: RandR considering mode (%d,%d)\n", width, height);
+          if (width >= w && height >= h && width <= nw && height <= nh) {
+            if (width != nw || height != nh)
+              best_rate = 0; /* geometry changed, start over rate search */
+            nw = width;
+            nh = height;
+            int rate = mi->dotClock / (mi->hTotal * mi->vTotal);
+            if (rate > best_rate) {
+              best_rate = rate;
+              mode_id = mi->id;
+            }
+          }
+        }
+      }
+      if (mode_id == -1) {
+        error("X: RandR found no suitable mode for CRTC output %d!\n", output_idx);
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRFreeOutputInfo(oi);
+
+      /* Change to fullscreen; save window config first. */
+      X_printf("X: RandR mode asking for (%d,%d); setting %dx%d@%d mode %d\n", w, h, nw, nh, best_rate, mode_id);
+      X_printf("X: RandR saving old mode %d crtc %d\n", (int)ci->mode, (int)crtc);
+      xrandr_win_mode = ci->mode;
+      xrandr_win_crtc = crtc;
+			xrandr_win_xpos = dosemu_x;
+			xrandr_win_ypos = dosemu_y;
+			/* Position window at (0,0) on *this* CRTC. */
+			dosemu_x = ci->x;
+			dosemu_y = ci->y;
+      XRRSetCrtcConfig(display, sr, crtc, CurrentTime, ci->x, ci->y, mode_id, ci->rotation, ci->outputs, ci->noutput);
+      XRRFreeCrtcInfo(ci);
+      XRRFreeScreenResources(sr);
+      /* Callers always set this themselves, but anyway... */
+      mainwindow = fullscreenwindow;
+    }
+  } else /* Only attempt VidMode or non-modechange fullscreen if RandR is disabled. */
+#endif /* HAVE_XRANDR */
+
 #ifdef HAVE_XVIDMODE
   if (xf86vm_ok) {
     static XF86VidModeModeLine vidmode_modeline;
@@ -2402,6 +2587,10 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height)
     XWarpPointer(display, None, drawwindow, 0, 0, 0, 0, mx, my);
   *new_width = nw;
   *new_height = nh;
+  if (new_x != NULL)
+    *new_x = dosemu_x;
+  if (new_y != NULL)
+    *new_y = dosemu_y;
 }
 
 /*
-- 
1.9.1
 | 
| 
      
      
      From: Ryan C. U. <nem...@ic...> - 2015-01-18 06:07:49
      
     | 
| From: "Ryan C. Underwood" <ne...@ic...>
XRandR support is fully added and works properly in a multihead configuration
if the user's version is at least 1.2.  It works basically like the existing
XVidMode code and is preferred whenever it is available.  It will also properly
restore the dosemu window's position when exiting fullscreen mode.
Keyboard and mouse grabbing had to be reworked to account for multihead (e.g.,
fullscreen DOS window on one output but with the ability to use applications on
a different output).
Signed-off-by: Ryan C. Underwood <ne...@ic...>
---
 configure.ac            |  17 +++
 src/include/config.h.in |   3 +
 src/plugin/X/X.c        | 275 ++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 252 insertions(+), 43 deletions(-)
diff --git a/configure.ac b/configure.ac
index a5b4df9..f444b31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,6 +376,20 @@ if test "$have_x" = "yes" ; then
                  [#include <X11/Xlib.h>])
     fi
 
+    AC_ARG_ENABLE(xrandr,
+              {  --disable-xrandr        do NOT use the XRandR extension])
+    if test "$enable_xrandr" != "no" ; then
+      AC_CHECK_LIB(Xrandr, XRRQueryVersion, enable_xrandr="yes", enable_xrandr="no")
+    fi
+    if test "$enable_xrandr" = "no" ; then
+               AC_MSG_NOTICE(Compiling without the XRandR extension)
+    else
+         AC_CHECK_HEADER(X11/extensions/Xrandr.h,
+     [AC_DEFINE(HAVE_XRANDR,1) X_LIBS="-lXrandr $X_LIBS"],
+                 AC_MSG_NOTICE(Compiling without the XRandR extension),
+                 [#include <X11/Xlib.h>])
+    fi
+
     LIBS=$SLIBS
     unset SLIBS
 
@@ -768,6 +782,9 @@ AH_TEMPLATE([HAVE_MITSHM],
 AH_TEMPLATE([HAVE_XVIDMODE],
 [ Define this if you want to use the XF86 video mode extension ])
 
+AH_TEMPLATE([HAVE_XRANDR],
+[ Define this if you want to use the XRandR extension ])
+
 AH_TEMPLATE([ASPI_SUPPORT],
 [ Define this for ASPI (generic SCSI) support ])
 
diff --git a/src/include/config.h.in b/src/include/config.h.in
index 6ef8763..7cf2248 100644
--- a/src/include/config.h.in
+++ b/src/include/config.h.in
@@ -134,6 +134,9 @@ EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MID
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define this if you want to use the XRandR extension */
+#undef HAVE_XRANDR
+
 /* Define this if you want to use the XF86 video mode extension */
 #undef HAVE_XVIDMODE
 
diff --git a/src/plugin/X/X.c b/src/plugin/X/X.c
index 8e188c8..4a22b0f 100644
--- a/src/plugin/X/X.c
+++ b/src/plugin/X/X.c
@@ -235,6 +235,10 @@
 #include <X11/extensions/xf86vmode.h>
 #endif
 
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #include "emu.h"
 #include "timers.h"
 #include "bios.h"
@@ -320,6 +324,13 @@ static int modecount;
 static XF86VidModeModeInfo **vidmode_modes;
 #endif
 
+#ifdef HAVE_XRANDR
+static int xrandr_ok = 0;
+static RRMode xrandr_win_mode = None;
+static RRCrtc xrandr_win_crtc = None;
+static int xrandr_win_xpos, xrandr_win_ypos;
+#endif
+
 Display *display;		/* used in plugin/?/keyb_X_keycode.c */
 static int screen;
 static Visual *visual;
@@ -369,7 +380,7 @@ static unsigned ximage_bits_per_pixel;
 static unsigned ximage_mode;
 static vga_emu_update_type veut;
 
-static int grab_active = 0, kbd_grab_active = 0;
+static int grab_active = 0, kbd_grab_active = 0, force_kbd_grab = 0;
 #if CONFIG_X_MOUSE
 static char *grab_keystring = "Home";
 static KeySym grab_keysym = NoSymbol;
@@ -402,6 +413,10 @@ static void X_dga_done(void);
 static void X_xf86vm_init(void);
 static void X_xf86vm_done(void);
 #endif
+#ifdef HAVE_XRANDR
+static void X_randr_init(void);
+static void X_randr_done(void);
+#endif
 
 static void X_keymap_init(void);
 
@@ -432,7 +447,7 @@ static void resize_ximage(unsigned, unsigned);
 static int X_set_videomode(int, int, int);
 static void X_resize_text_screen(void);
 static void toggle_fullscreen_mode(int);
-static void X_vidmode(int w, int h, int *new_width, int *new_height);
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height);
 static void lock_window_size(unsigned wx_res, unsigned wy_res);
 
 /* screen update/redraw functions */
@@ -447,6 +462,7 @@ static Cursor create_invisible_cursor(void);
 /* text mode cursor manipulation stuff */
 static void X_update_cursor(void);
 
+static void toggle_kbd_grab(void);
 #if CONFIG_X_MOUSE
 /* mouse related code */
 static void set_mouse_position(int, int);
@@ -593,6 +609,10 @@ int X_init()
   X_xf86vm_init();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_init();
+#endif
+
   /* see if we find out something useful about our X server... -- sw */
   X_keymap_init();
 
@@ -806,6 +826,10 @@ void X_close()
   X_xf86vm_done();
 #endif
 
+#ifdef HAVE_XRANDR
+  X_randr_done();
+#endif
+
   X_load_text_font(display, 0, drawwindow, NULL, NULL, NULL);
   if(our_window) {
     XDestroyWindow(display, drawwindow);
@@ -1026,12 +1050,51 @@ static void X_xf86vm_init(void)
 static void X_xf86vm_done(void)
 {
   if (mainwindow == fullscreenwindow)
-    X_vidmode(-1, -1, &w_x_res, &w_y_res);
+    X_vidmode(-1, -1, NULL, NULL, &w_x_res, &w_y_res);
   xf86vm_ok = 0;
 }
 
 #endif
 
+#ifdef HAVE_XRANDR
+static void X_randr_init(void)
+{
+  int param1, param2;
+  if (XRRQueryExtension(display, ¶m1, ¶m2) &&
+      XRRQueryVersion(display, ¶m1, ¶m2))
+  {
+    X_printf("X: RandR Extension version %d.%d\n", param1, param2);
+    if (param1 <= 1 && param2 < 2) {
+      X_printf("X: RandR version doesn't support stretched desktop or multihead!\n");
+      /* continue anyway, as it should work for single head */
+    }
+    xrandr_ok = 1;
+  }
+}
+
+static void X_randr_exit_fullscreen(void)
+{
+  if (xrandr_win_crtc != None && xrandr_win_mode != None) {
+    X_printf("X: RandR restoring old mode %d crtc %d\n", (int)xrandr_win_mode, (int)xrandr_win_crtc);
+    XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+    XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, xrandr_win_crtc);
+    XRRSetCrtcConfig(display, sr, xrandr_win_crtc, CurrentTime, ci->x, ci->y, xrandr_win_mode, ci->rotation, ci->outputs, ci->noutput);
+    XRRFreeCrtcInfo(ci);
+    XRRFreeScreenResources(sr);
+    xrandr_win_crtc = xrandr_win_mode = None;
+  }
+}
+
+static void X_randr_done(void)
+{
+  if (mainwindow == fullscreenwindow) {
+    X_printf("X: RandR leaving fullscreen mode\n");
+    X_randr_exit_fullscreen();
+  }
+  xrandr_ok = 0;
+}
+#endif /* HAVE_XRANDR */
+
 /*
  * Handle 'auto'-entries in dosemu.conf, namely
  * $_X_keycode & $_layout
@@ -1229,15 +1292,10 @@ static void toggle_kbd_grab(void)
 {
   if(kbd_grab_active ^= 1) {
     X_printf("X: keyboard grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
-    }
-  }
-  else {
+    XGrabKeyboard(display, drawwindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+  } else {
     X_printf("X: keyboard grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabKeyboard(display, CurrentTime);
-    }
+    XUngrabKeyboard(display, CurrentTime);
   }
   X_change_config(CHG_TITLE, NULL);
 }
@@ -1247,19 +1305,15 @@ static void toggle_mouse_grab(void)
   if(grab_active ^= 1) {
     config.mouse.use_absolute = 0;
     X_printf("X: mouse grab activated\n");
-    if (mainwindow != fullscreenwindow) {
-      XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                   GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
-    }
+    XGrabPointer(display, drawwindow, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+		 GrabModeAsync, GrabModeAsync, drawwindow,  None, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(1);
   }
   else {
     config.mouse.use_absolute = 1;
     X_printf("X: mouse grab released\n");
-    if (mainwindow != fullscreenwindow) {
-      XUngrabPointer(display, CurrentTime);
-    }
+    XUngrabPointer(display, CurrentTime);
     X_set_mouse_cursor(mouse_cursor_visible, mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_sync_coords(mouse_x, mouse_y, w_x_res, w_y_res);
     mouse_enable_native_cursor(0);
@@ -1338,7 +1392,7 @@ static void X_wait_unmapped(Window win)
 
 static void toggle_fullscreen_mode(int init)
 {
-  int resize_height, resize_width;
+  int reloc_x, reloc_y, resize_height, resize_width;
 
   if (!init) {
     XUnmapWindow(display, mainwindow);
@@ -1351,15 +1405,12 @@ static void toggle_fullscreen_mode(int init)
     toggling_fullscreen = 2;
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
-    if (!grab_active) {
-      toggle_mouse_grab();
-      force_grab = 1;
-    }
-    X_vidmode(x_res, y_res, &resize_width, &resize_height);
+    X_vidmode(x_res, y_res, &reloc_x, &reloc_y, &resize_width, &resize_height);
     mainwindow = fullscreenwindow;
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     } else {
       shift_x = (resize_width - w_x_res) / 2;
       shift_y = (resize_height - w_y_res) / 2;
@@ -1368,30 +1419,35 @@ static void toggle_fullscreen_mode(int init)
     XMapWindow(display, mainwindow);
     XRaiseWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, shift_x, shift_y);
-    XGrabPointer(display, drawwindow, True,
-                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
-                 GrabModeAsync, GrabModeAsync, drawwindow,  None,
-                 CurrentTime);
-    XGrabKeyboard(display, drawwindow, True, GrabModeAsync,
-                  GrabModeAsync, CurrentTime);
+    if (!grab_active) {
+      toggle_mouse_grab();
+      force_grab = 1;
+    }
+    if (!kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 1;
+    }
   } else {
     X_printf("X: entering windowed mode!\n");
     w_x_res = saved_w_x_res;
     w_y_res = saved_w_y_res;
-    XUngrabKeyboard(display, CurrentTime);
-    XUngrabPointer(display, CurrentTime);
     mainwindow = normalwindow;
-    X_vidmode(-1, -1, &resize_width, &resize_height);
+    X_vidmode(-1, -1, &reloc_x, &reloc_y, &resize_width, &resize_height);
     if (vga.mode_class == GRAPH || use_bitmap_font) {
-      XResizeWindow(display, mainwindow, resize_width+1, resize_height+1);
-      XResizeWindow(display, drawwindow, resize_width+1, resize_height+1);
+      X_printf("X: relocating dosemu window to %d,%d\n", reloc_x, reloc_y);
+      XMoveResizeWindow(display, mainwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
+      XMoveResizeWindow(display, drawwindow, reloc_x, reloc_y, resize_width+1, resize_height+1);
     }
     XMapWindow(display, mainwindow);
     XReparentWindow(display, drawwindow, mainwindow, 0, 0);
     if (force_grab && grab_active) {
       toggle_mouse_grab();
+      force_grab = 0;
+    }
+    if (force_kbd_grab && kbd_grab_active) {
+      toggle_kbd_grab();
+      force_kbd_grab = 0;
     }
-    force_grab = 0;
   }
   if(vga.mode_class == TEXT && !use_bitmap_font) {
     X_resize_text_screen();
@@ -1550,6 +1606,7 @@ static void X_handle_events(void)
               toggle_mouse_grab();
               break;
             } else if (keysym == XK_k) {
+              force_kbd_grab = 0;
               toggle_kbd_grab();
               break;
             } else if (keysym == XK_f) {
@@ -1652,6 +1709,12 @@ static void X_handle_events(void)
 	    }
 	    set_mouse_buttons(e.xcrossing.state);
 	    mouse_really_left_window = 0;
+	    /* Grab keyboard if fullscreen (i.e., entering window from another
+	     * CRTC in a multihead system.  Otherwise we can't type.*/
+	    if (mainwindow == fullscreenwindow && !kbd_grab_active) {
+	      toggle_kbd_grab();
+	      force_kbd_grab = 1;
+	    }
           }
 	  break;
 
@@ -1666,6 +1729,12 @@ static void X_handle_events(void)
             X_printf("X: bogus LeaveNotify event\n");
             mouse_really_left_window = 0;
           }
+	  /* Release keyboard if fullscreen, mouse leaves window, and the
+	   * current grab had been forced by dosemu. */
+	  if (mainwindow == fullscreenwindow && kbd_grab_active && !force_kbd_grab) {
+	    toggle_kbd_grab();
+	    force_kbd_grab = 0;
+	  }
 	  break;
 
         case ConfigureNotify:
@@ -2066,7 +2135,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   sh.width = sh.min_width = sh.max_width = wx_res;
   sh.height = sh.min_height = sh.max_height = wy_res;
 
-  sh.flags = PSize  | PMinSize | PMaxSize;
+  sh.flags = PPosition | PSize | PMinSize | PMaxSize;
   if(config.X_fixed_aspect || config.X_aspect_43) sh.flags |= PAspect;
   if (use_bitmap_font) {
     sh.flags |= PResizeInc;
@@ -2086,7 +2155,7 @@ static void lock_window_size(unsigned wx_res, unsigned wy_res)
   x_fill = w_x_res;
   y_fill = w_y_res;
   if (mainwindow == fullscreenwindow)
-    X_vidmode(x_res, y_res, &x_fill, &y_fill);
+    X_vidmode(x_res, y_res, NULL, NULL, &x_fill, &y_fill);
 
   XResizeWindow(display, mainwindow, x_fill+1, y_fill+1);
 
@@ -2206,8 +2275,9 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     saved_w_x_res = w_x_res;
     saved_w_y_res = w_y_res;
     lock_window_size(w_x_res, w_y_res);
+    /* lock_window_size() already did this, but there must be a reason ... */
     if(mainwindow == fullscreenwindow) {
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
     if (!use_bitmap_font) {
       w_x_res = saved_w_x_res;
@@ -2229,7 +2299,7 @@ int X_set_videomode(int mode_class, int text_width, int text_height)
     if(mainwindow == fullscreenwindow) {
       saved_w_x_res = w_x_res;
       saved_w_y_res = w_y_res;
-      X_vidmode(x_res, y_res, &w_x_res, &w_y_res);
+      X_vidmode(x_res, y_res, NULL, NULL, &w_x_res, &w_y_res);
     }
 
     create_ximage();
@@ -2319,13 +2389,128 @@ void X_resize_text_screen()
 /*
  * Change to requested video mode or the closest greater one.
  */
-static void X_vidmode(int w, int h, int *new_width, int *new_height)
+static void X_vidmode(int w, int h, int *new_x, int *new_y, int *new_width, int *new_height)
 {
   int nw, nh, mx, my, shift_x, shift_y;
 
   nw = DisplayWidth(display, screen);
   nh = DisplayHeight(display, screen);
 
+  int dosemu_x = -1, dosemu_y = -1;
+  XWindowAttributes attr;
+  if (XGetWindowAttributes(display, rootwindow, &attr)) {
+    X_printf("X: X_vidmode: root window size (%d,%d)\n",
+        attr.width, attr.height);
+
+    Window child;
+    if (XTranslateCoordinates(display, normalwindow, rootwindow, 0, 0, &dosemu_x, &dosemu_y, &child)
+        && XGetWindowAttributes(display, normalwindow, &attr)) {
+      X_printf("X: X_vidmode: dosemu window loc (%d,%d) size (%d,%d)\n",
+          dosemu_x, dosemu_y, attr.width, attr.height);
+    }
+  }
+
+#ifdef HAVE_XRANDR
+  if (xrandr_ok) {
+    if (w == -1 && h == -1) {
+      /* Return to window. */
+      X_printf("X: RandR leaving fullscreen mode\n");
+      X_randr_exit_fullscreen();
+			dosemu_x = xrandr_win_xpos;
+			dosemu_y = xrandr_win_ypos;
+    } else if (mainwindow != fullscreenwindow) {
+      X_printf("X: RandR entering fullscreen mode\n");
+      /* Find which CRTC 'window' dosemu's upper left corner is within. */
+      XRRScreenResources *sr = XRRGetScreenResourcesCurrent(display, mainwindow);
+      RRCrtc crtc = None;
+			int i;
+      for (i = 0; i < sr->ncrtc; i++) {
+        XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, sr->crtcs[i]);
+        if (ci->mode == None) {
+          /* crtc disabled, try another */
+          XRRFreeCrtcInfo(ci);
+          continue;
+        }
+        X_printf("X: RandR considering CRTC (%d+%d,%d+%d)\n", ci->x, ci->width, ci->y, ci->height);
+        if (dosemu_x >= ci->x && dosemu_x < ci->x + ci->width &&
+            dosemu_y >= ci->y && dosemu_y < ci->y + ci->height)
+        {
+          X_printf("X: RandR using this CRTC\n");
+          crtc = sr->crtcs[i];
+          XRRFreeCrtcInfo(ci);
+          break;
+        }
+        XRRFreeCrtcInfo(ci);
+      }
+      if (crtc == None) {
+        error("X: RandR found no suitable CRTC!\n");
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRCrtcInfo *ci = XRRGetCrtcInfo(display, sr, crtc);
+
+      /* XXX: Use the first CRTC output always.  In what display configuration
+       * could this break? */
+      int output_idx = 0;
+      XRROutputInfo *oi = XRRGetOutputInfo(display, sr, ci->outputs[output_idx]);
+
+      /* Find the best mode supported by this CRTC by first finding the
+       * closest fit that is at least as large as the DOS screen, then the
+       * best refresh rate at that size.  To do this we have to find every mode
+       * available in the output, then search the screen modes for its ID. */
+      int mode_id = -1;
+      int best_rate = 0;
+      for (i = 0; i < oi->nmode; i++) {
+        RRMode output_mode = oi->modes[i];
+				int j;
+        for (j = 0; j < sr->nmode; j++) {
+          const XRRModeInfo *mi = &sr->modes[j];
+          if (mi->id != output_mode)
+            continue;
+          int width = mi->width;
+          int height = mi->height;
+          X_printf("X: RandR considering mode (%d,%d)\n", width, height);
+          if (width >= w && height >= h && width <= nw && height <= nh) {
+            if (width != nw || height != nh)
+              best_rate = 0; /* geometry changed, start over rate search */
+            nw = width;
+            nh = height;
+            int rate = mi->dotClock / (mi->hTotal * mi->vTotal);
+            if (rate > best_rate) {
+              best_rate = rate;
+              mode_id = mi->id;
+            }
+          }
+        }
+      }
+      if (mode_id == -1) {
+        error("X: RandR found no suitable mode for CRTC output %d!\n", output_idx);
+        *new_width = w;
+        *new_height = h;
+        return;
+      }
+      XRRFreeOutputInfo(oi);
+
+      /* Change to fullscreen; save window config first. */
+      X_printf("X: RandR mode asking for (%d,%d); setting %dx%d@%d mode %d\n", w, h, nw, nh, best_rate, mode_id);
+      X_printf("X: RandR saving old mode %d crtc %d\n", (int)ci->mode, (int)crtc);
+      xrandr_win_mode = ci->mode;
+      xrandr_win_crtc = crtc;
+			xrandr_win_xpos = dosemu_x;
+			xrandr_win_ypos = dosemu_y;
+			/* Position window at (0,0) on *this* CRTC. */
+			dosemu_x = ci->x;
+			dosemu_y = ci->y;
+      XRRSetCrtcConfig(display, sr, crtc, CurrentTime, ci->x, ci->y, mode_id, ci->rotation, ci->outputs, ci->noutput);
+      XRRFreeCrtcInfo(ci);
+      XRRFreeScreenResources(sr);
+      /* Callers always set this themselves, but anyway... */
+      mainwindow = fullscreenwindow;
+    }
+  } else /* Only attempt VidMode or non-modechange fullscreen if RandR is disabled. */
+#endif /* HAVE_XRANDR */
+
 #ifdef HAVE_XVIDMODE
   if (xf86vm_ok) {
     static XF86VidModeModeLine vidmode_modeline;
@@ -2402,6 +2587,10 @@ static void X_vidmode(int w, int h, int *new_width, int *new_height)
     XWarpPointer(display, None, drawwindow, 0, 0, 0, 0, mx, my);
   *new_width = nw;
   *new_height = nh;
+  if (new_x != NULL)
+    *new_x = dosemu_x;
+  if (new_y != NULL)
+    *new_y = dosemu_y;
 }
 
 /*
-- 
1.9.1
 | 
| 
      
      
      From: Stas S. <st...@li...> - 2014-09-28 08:15:49
      
     | 
| 21.09.2014 05:55, Bart Oldeman пишет: > Stas Sergeevwrote: > > Eric Auer wrote: > >> change is to allow contributing under "GPLv2 or later". > > Did any other DOSEMU experts have a strong opinion > > about this? Or did people not care which of the two > > variants should be used, except for Bart who prefers > > the old variant? > > > Eric, you can see other Eric's (Biederman) replies in the archives here: > https://www.mail-archive.com/dos...@li.../index.html#00333 > > I mostly agree with him, and he was involved in DOSEMU before me so > knows slightly more about that history before. OK, Eric's concerns are addressed, patch applied: https://sourceforge.net/p/dosemu/code/ci/cc971eae4738016c22b3d2e1b3473df2176c8e29 > IANAL but I suspect that somebody can fork the Linux kernel and remove > that text just as you can fork dosemu Should I really do that? :( A big pain for all users and distributors... But we need to get off from that point, one way or another. > However nobody can relicense the kernel or DOSEMU from GPLv2 to "GPLv2 > or later" But I can, thanks to GPL faq (if I do the fork, of course). What stops you from doing so, was never clarified. > or "GPLv3" or "GPLv3 or later" Indeed, this is not possible. > So I am in favour of keeping our language, maybe clarify it a bit. Me too, the clarification is now in devel. Of course without any "Linus did the same, we allow dynamic linking and interpret GPL over what is written" blabbering *shudder*, but its still there. What else needs to be done to get us any further for the merge? |