This example demonstrates how the use of the XPLMSetWindowGravity() API to cause your window to dynamically resize based on the X-Plane window’s size.

The gravity API keeps the SDK-created window fixed to the left and right sides, so it grows & shrinks with the X‑Plane window.
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include <string.h>
#include <stdio.h>
#if IBM
	#include <windows.h>
#endif
#if LIN
	#include <GL/gl.h>
#elif __GNUC__
	#include <OpenGL/gl.h>
#else
	#include <GL/gl.h>
#endif

#ifndef XPLM300
	#error This is made to be compiled against the XPLM300 SDK
#endif

static XPLMWindowID	g_window;

void				draw(XPLMWindowID in_window_id, void * in_refcon);

int					dummy_mouse_handler(XPLMWindowID in_window_id, int x, int y, int is_down, void * in_refcon) { return 0; }
XPLMCursorStatus	dummy_cursor_status_handler(XPLMWindowID in_window_id, int x, int y, void * in_refcon) { return xplm_CursorDefault; }
int					dummy_wheel_handler(XPLMWindowID in_window_id, int x, int y, int wheel, int clicks, void * in_refcon) { return 0; }
void				dummy_key_handler(XPLMWindowID in_window_id, char key, XPLMKeyFlags flags, char virtual_key, void * in_refcon, int losing_focus) { }

PLUGIN_API int XPluginStart(
						char *		outName,
						char *		outSig,
						char *		outDesc)
{
	strcpy(outName, "GravitySamplePlugin");
	strcpy(outSig, "xpsdk.examples.gravitysampleplugin");
	strcpy(outDesc, "A test plug-in that demonstrates the gravity features of the X-Plane 11 GUI plugin API.");

	// We're not guaranteed that the main monitor's lower left is at (0, 0)... we'll need to query for the global desktop bounds!
	int global_desktop_bounds[4]; // left, bottom, right, top
	XPLMGetScreenBoundsGlobal(&global_desktop_bounds[0], &global_desktop_bounds[3], &global_desktop_bounds[2], &global_desktop_bounds[1]);

	XPLMCreateWindow_t params;
	params.structSize = sizeof(params);
	// Set the window bounds such that we stretch the full *width* of the global desktop, and cover the top 200 bx
	params.left = global_desktop_bounds[0];
	params.bottom = global_desktop_bounds[3] - 200;
	params.right = global_desktop_bounds[2];
	params.top = global_desktop_bounds[3];
	params.visible = 1;
	params.drawWindowFunc = draw;
	params.handleMouseClickFunc = dummy_mouse_handler;
	params.handleRightClickFunc = dummy_mouse_handler;
	params.handleMouseWheelFunc = dummy_wheel_handler;
	params.handleKeyFunc = dummy_key_handler;
	params.handleCursorFunc = dummy_cursor_status_handler;
	params.refcon = NULL;
	params.layer = xplm_WindowLayerFlightOverlay; // stick our window beneath all floating windows (like the X-Plane 11 map)
	params.decorateAsFloatingWindow = 0;
	
	g_window = XPLMCreateWindowEx(&params);
	
	XPLMSetWindowPositioningMode(g_window, xplm_WindowPositionFree, -1);
	// As the X-Plane window resizes, glue our left and right edges to the sides of the screen
	// (causing our width to grow and shrink to match the window size), but keep a constant
	// height for our window (with the same y position relative to the window's top).
	XPLMSetWindowGravity(g_window, 0, 1, 1, 1);
	
	return (g_window != NULL);
}

PLUGIN_API void	XPluginStop(void)
{
	// Since we created the window, we'll be good citizens and clean it up
	XPLMDestroyWindow(g_window);
	g_window = NULL;
}

PLUGIN_API void XPluginDisable(void) { }
PLUGIN_API int  XPluginEnable(void)  { return 1; }
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom, int inMsg, void * inParam) { }

void	draw(XPLMWindowID in_window_id, void * in_refcon)
{
	XPLMSetGraphicsState(
			0 /* no fog */,
			0 /* 0 texture units */,
			0 /* no lighting */,
			0 /* no alpha testing */,
			1 /* do alpha blend */,
			1 /* do depth testing */,
			0 /* no depth writing */
	);
	
	int b[4];
	XPLMGetWindowGeometry(in_window_id, &b[0], &b[3], &b[2], &b[1]);
	
	// Draw our window's translucent background overlay
	XPLMDrawTranslucentDarkBox(b[0], b[3], b[2], b[1]);
	
	// Display the window bounds (centered within the window)
	char scratch_buffer[150];
	sprintf(scratch_buffer, "Window bounds: %d %d %d %d", b[0], b[1], b[2], b[3]);
	float col_white[] = {1.0, 1.0, 1.0};
	int text_width = XPLMMeasureString(xplmFont_Proportional, scratch_buffer, strlen(scratch_buffer));
	float text_midpoint_x = (b[2] + b[0]) / 2;
	XPLMDrawString(col_white, text_midpoint_x - text_width / 2, (b[3] + b[1]) / 2, scratch_buffer, NULL, xplmFont_Proportional);
}

7 comments on “X-Plane 11 Window Gravity Sample

  1. Thanks a lot Tyler,

    What’s about using it on X-Plane v10 ?

    Probably a stupid question but where we can download the last SDK please ?

    Cheers
    Stef

    1. Shhh… you’ve found my super-secret SDK version 3.0 samples. 🙂 Version 3 of the SDK will be released with the impending X-Plane 11.10 release. (Watch the blog for an announcement on where to get it.)

      There are no plans to backport new SDK functionality to X-Plane 10, though.

      1. Ah. Being stealthy, are we? 😉

        So the SDK will be updated sooner rather than later! That’s really good news – and very important for commercial devs to know. New toys to play with, new ways to break old toys.

        Joy?

        Watching the blog like a hawk. 😀

      2. Hoo, I’m happy. Don’t worry, I’ll say no word 🙂
        I’m impatient to read more, The way appears to be simple to use and I’m sure you will enjoy plugin developers with that. GoodWay will be HAPPY to use it 🙂

        Don’t worry, Shhhhhh…. 🙂 THANKS !!!!!

        Cheers
        Stef

  2. Tyler,

    Is there a list of enhancements you are planning for the new SDK? I’m interested being able to create undocked windows and have scale-able fonts using XPStandardWidgets.

    I’ also interested if we have a bit more control over the mouse events, like a right mouse click.

    Mark

Leave a Reply

Your email address will not be published. Required fields are marked *

Please do not report bugs in the blog comments.
Only bugs reported via the X-Plane Bug Reporter are tracked.