I've been playing around with the i3 window manager a lot lately, and I have
to say I enjoy it very much! But one default setting that tripped me up (as
set by i3-config-wizard) was the key bindings for workspace switching:
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
# ...
This works well until you start naming your workspaces. With these bindings,
you will switch to workspace name "1", not number "1". So if you rename
workspace 1 to "1: Firefox" and press Mod5+1, you'll end up opening a new
workspace instead of going to the "1: Firefox" workspace. Not very intuitive!
Luckily, we can easily get the desired behavior with a slight tweak to the
config file:
bindsym $mod+1 workspace number 1
bindsym $mod+2 workspace number 2
bindsym $mod+3 workspace number 3
# ...
Posted Thu 11 July 2013
by Justin Holewinski in General
(Linux, i3)
For the past week, I've been giving Windows 8 a serious try. I've
dabbled with the various preview versions, but now it's time to try the
released version. I've read the reviews, saw the mixed reactions to the
new "Modern UI", and decided to see for myself how I feel about
it. Generally speaking, I don't mind the new interface. My usual method
of launching a program was pressing the Win key, typing the first few
letters of the application name, and then hitting Enter. Still works in
the Start Screen. Start Menu vs. Start Screen, it doesn't bother me.
Except for one little detail...
... the complete lack of multi-monitor support in the Modern UI!
Simply put, there can only be one full-screen Modern UI app displayed at
a time. So if I open, say, Mail on one screen and attempt to open Maps
on another screen, the screen showing Mail will go back to the desktop.
To make matters worse, the Start Screen counts as a Modern UI app in
this regard. If I have Mail open on one screen and try to open the
Start Screen on another screen to launch an application, the screen
showing Mail goes back to the desktop and I have to alt+tab back to it.
Talk about a disruption in my workflow!
Did I mention my main desktop is triple-head? It comes in handy for
coding. All of the Windows 8 reviews I read talk about the pros and
cons of the new Modern UI, but I rarely see any reference to the
complete lack of multi-monitor support in it. I'm not sure if this is
just a feature oversight, or a more fundamental limitation in the model
used for WinRT apps. Is there a fundamental technical limitation in
the operating system that prevents multiple Modern UI apps to be visible
at the same time? If the Modern UI is the future, I sure hope they get
this fixed ASAP! For now, it's easy enough to just avoid Modern UI apps
altogether, but what happens in the future when I find an app I want to
keep open on one of my screens?
Perhaps more disturbing, this is becoming a trend in mainstream
operating systems. While Windows 8 has this limitation for Modern UI
apps, full-screen apps in Mac OS X are not really any better. If I
full-screen an application in a multi-monitor configuration, I get that
app on one monitor and a pretty background on all others. I would much
rather have the ability to put multiple apps in full-screen mode
side-by-side, or perhaps have the option to have a full-screen app next
to a desktop workspace on another monitor. At least I can have multiple
workspaces, though.
Perhaps I'm just too adjusted to my Linux multi-monitor
configurations...
Posted Tue 06 November 2012
by Justin Holewinski in General
(Windows, Desktop)
I was playing around with the Unreal Development Kit this evening, and
discovered a rather interesting quirk in the handling of braces within
UnrealScript. All of the sample code I read use a syntax style that
places opening braces on the following line:
event PostBeginPlay()
{
// Do something
}
However, my typical style places the opening brace on the current line:
event PostBeginPlay() {
// Do something
}
Unfortunately, this does not seem to work for defaultproperties
blocks. If you place the brace on the same line, the compiler will not
give you any warnings or errors, but the entire defaultproperties
block is just ignored!
So this code works:
defaultproperties
{
PlayerControllerClass=class'MyPlayerController'
}
while the following code compiles but silently just ignores all of the
contained settings:
defaultproperties {
PlayerControllerClass=class'MyPlayerController'
}
I was banging my head on the wall for at least an hour figuring this one
out!
I hope this can help prevent someone else from repeating my mistake.
Posted Sat 17 March 2012
by Justin Holewinski in Programming
(Unreal)
I've converted my old Space Hogs game project to XNA 4.0 (it was
originally written in XNA 1.0). There were enough API changes to make it
a pain, but I think I have everything working now.
This game was developed by myself, Jason Kim, Joseph Ahn, Vjekoslav
Kovacevic, and Daniel Guinn for a computer animation class during Winter
Quarter 2007.
You can find a zip file here. This requires XNA 4.0 and the February
2010 DX packages to be installed on your machine. For convenience, I've
included both of the redistributable packages in the zip file.
The source can be found on BitBucket.
Enjoy!
Posted Fri 17 February 2012
by Justin Holewinski in Programming
(Windows, Games)
(If you're in a hurry, the full source can be found on my BitBucket
account)
When it comes to GUI frameworks for C++, it's very hard to beat Qt.
It's modular, easy to use, and available on practically any desktop
system (and even a few mobile systems). The MOC'ing can get a bit
annoying, but IDE and command-line support is very mature at this point.
However, only OpenGL is supported currently for real-time 3D rendering.
If you want to render to a Qt widget from a Direct3D 11 device, you end
up having to do a lot of setup yourself.
Unfortunately, there is not a lot of information out on the internet
about setting up Direct3D to play nice with Qt. Most of the information
is either out-dated, or only applies to Direct3D 9. Lately, I've been
playing around with this and I want to share my method for combining
Direct3D 11 and Qt.
Creating the Direct3D 11 Device
Now that we have a basic widget that can support Direct3D rendering, we
can initialize the Direct3D 11 device we want. This procedure is mostly
identical to setting up Direct3D in a raw window. The only difference is
that we must use the width(), height(), and winId() methods
to return the widget size and native window handle, respectively:
| swapChainDesc_.BufferCount = 1;
swapChainDesc_.BufferDesc.Width = width();
swapChainDesc_.BufferDesc.Height = height();
swapChainDesc_.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc_.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc_.SampleDesc.Count = 4;
swapChainDesc_.SampleDesc.Quality = 0;
swapChainDesc_.Windowed = true;
swapChainDesc_.OutputWindow = winId();
swapChainDesc_.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc_.BufferDesc.RefreshRate.Denominator = 1;
|
Everything else remains the same... pretty easy, huh? :)
Handling Paint Events
Remember the paintEvent override from the widget class definition?
We can simply implement it with a call to some rendering function:
| void D3DRenderWidget::paintEvent(QPaintEvent* evt) {
render();
}
|
Here, render() is just some arbitrary method that uses the Direct3D
11 device to render something to the primary swap chain.
Handling Resize Events
Resize events are perhaps the hardest events to handle when integrating
Direct3D 11 and Qt. To resize our swap chain, we need to release all
device-allocated resources, and reallocate them. The procedure I follow
is:
| void D3DRenderWidget::resizeEvent(QResizeEvent* evt) {
releaseBuffers();
swapChain_->ResizeBuffers(1, width(), height(), swapChainDesc_.BufferDesc.Format, 0);
swapChain_->GetDesc(&swapChainDesc_);
viewport_.Width = width();
viewport_.Height = height();
createBuffers();
}
|
We start by releasing all of the buffers we had allocated (vertex
buffers, index buffers, shaders, textures, etc.). We then issue a resize
request to the swap chain, resize our rendering viewport, and then
recreate all of our needed buffers. In this snippet,
releaseBuffers() will call Release() on all buffers, and
createBuffers() will create all of the needed resources (again).
It would probably be easier to just allow the swap chain to grow and
just adjust the viewport if the widget shrinks, but this method shows
how to keep the swap chain the exact same size as the widget.
Conclusion
At this point, you should have a functional Direct3D 11 rendering
context for a Qt widget. For brevity, I have omitted most of the
Direct3D initialization code (this can be found in many places on the
web).
If you want to check out the complete sample program, it is located on
my BitBucket account. To build it, you need a relatively recent Qt
release, the DirectX SDK, and the Qt Visual Studio Add-in.
Posted Thu 16 February 2012
by Justin Holewinski in Programming
(Direct3D, Qt, Windows, C++)