JFrame’s don’t create their insets until after I pack the canvas on it, whereas Frames have them created when they’re made. That’s created a new and confusing problem with setting a maximized window. Here’s the code I now use to figure out how much room I have to draw on for my game:
Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
//because you can't add a canvas with size 0,0 because the JFrame will get angry
canvas.setSize((int)bounds.getWidth(), (int)bounds.getHeight());
panel.add(canvas);
frame.pack();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
Insets insets = frame.getInsets();
bounds.setFrame(bounds.getX(), bounds.getY(),
bounds.getWidth(),
bounds.getHeight() - insets.top + insets.bottom
);
canvas.setSize((int)bounds.getWidth(), (int)bounds.getHeight());
//Here's what my game logic will use
GAME_WIDTH = canvas.getWidth();
GAME_HEIGHT = canvas.getHeight();
And now everything works dandy, and it appears that with the JFrame change, both Windowed and Fullscreen modes are accelerated and now Fullscreen is SLIGHLTY faster for me than windowed mode. Neat!
Thank you oNyx for your direction 