Commits

Ivan Vučica committed 3c2af56

Added elementary EWMH window types compat. Attempt at optimizing texture binding.

Comments (0)

Files changed (2)

FPManagedWindow.h

 #import <GL/glx.h>
 #import "FPEventLoop.h"
 
+typedef enum _FPWindowType
+{
+	// EWMH window type (_NET_WM_WINDOW_TYPE)
+
+	FPWindowTypeNone = 0,
+	// TODO: to be more clean, use same order as in EWMH spec
+	FPWindowTypeMenu,
+	FPWindowTypeDropdownMenu,
+	FPWindowTypeDesktop,
+	FPWindowTypeUtility,
+	FPWindowTypeNormal,
+	FPWindowTypeSplash,
+	FPWindowTypeTooltip,
+	FPWindowTypeDialog
+} FPWindowType;
+
 @class FPWindowManager;
 // This class manages a single window not owned by Fireplace.
 @interface FPManagedWindow : NSObject<FPEventHandler>
 
 	BOOL _isMapped;
 
+	FPWindowType _windowType;
+
 	float _timeAlive;
 	float _mappedAtTimeAlive;
 

FPManagedWindow.m

 #import <X11/extensions/Xcomposite.h>
 #import <X11/extensions/shape.h>
 #import <X11/extensions/Xdamage.h>
+#import <X11/Xatom.h>
 #import <GL/gl.h>
 #import <GL/glu.h>
 #import <GL/glx.h>
 #import "FPWindowManager.h"
 #import "GLConfiguration.h"
 
+#define OPTIMIZED_TEXTURE_BUILD 0
+
 #if SWITCH_CONTEXTS
 #define SWITCH_TO_STAGE_CONTEXT \
 	[mainDisplay makeCurrentContext:[_manager glxContext] \
 	if(!_texture)
 		glGenTextures (1, &_texture);
 	XSync(display, None);
+
+#if OPTIMIZED_TEXTURE_BUILD
+	[self bindTexture];
+#endif
 	return;
 NSLog(@"texture; binding %p", _drawable);
 	if(glXBindTexImageEXT)
 	FPX11Display * mainDisplay = [FPX11Display mainDisplay];
 	Display * display = [mainDisplay display];
 
+#if OPTIMIZED_TEXTURE_BUILD
+	[self unbindTexture];
+#endif
 	if(glXReleaseTexImageEXT && _drawable)
 		glXReleaseTexImageEXT(display, _drawable, GLX_FRONT_EXT);
 
 	_hasAlpha = attr.visual ? (attr.depth > 3 * attr.visual->bits_per_rgb) : NO;
 	_overrideRedirect = attr.override_redirect;
 	_opacity = 1.0; // FIXME: is this right?
+
+	// TODO: use XGetTransientForHint(), often used for menus and
+	// similar usually undecorated items
+
+
+	// TODO: collect atoms once, in window manager
+	Atom _net_wm_window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
+	// TODO: to be more clean, use same order as in EWMH spec
+	Atom _net_wm_window_type_menu = XInternAtom(display, "_NET_WM_WINDOW_TYPE_MENU", False);
+	Atom _net_wm_window_type_dropdown_menu = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False);
+	Atom _net_wm_window_type_desktop = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
+	Atom _net_wm_window_type_utility = XInternAtom(display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
+	Atom _net_wm_window_type_normal = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
+	Atom _net_wm_window_type_splash = XInternAtom(display, "_NET_WM_WINDOW_TYPE_SPLASH", False);
+	Atom _net_wm_window_type_tooltip = XInternAtom(display, "_NET_WM_WINDOW_TYPE_TOOLTIP", False);
+	Atom _net_wm_window_type_dialog = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+	// ... etc
+	int result;
+	Atom rt; // TODO: check XGetWindowProperty manpage to see what rt is
+	Atom * windowType;
+	int format;
+	unsigned long n, extra;
+	
+	result = XGetWindowProperty(display, _window, _net_wm_window_type, 0, 100, False, XA_ATOM, &rt, &format, &n, &extra, (unsigned char**)&windowType);
+	if(result != Success || windowType == NULL)
+		_windowType = FPWindowTypeNone;
+	else 
+	{
+		for(n--; ((int)n)>=0; n--)
+		{
+			char * atom_name = XGetAtomName(display, windowType[n]);
+			printf("#%d: Wintype %d, name %s\n", n, windowType[n], atom_name);
+			XFree(atom_name);
+			// TODO: to be more clean, use same order as in EWMH spec
+			if(windowType[n] == _net_wm_window_type_menu)
+			{
+				_windowType = FPWindowTypeMenu;
+			}
+			else if(windowType[n] == _net_wm_window_type_dropdown_menu)
+			{
+				_windowType = FPWindowTypeDropdownMenu;
+			}
+			else if(windowType[n] == _net_wm_window_type_desktop)
+			{
+				_windowType = FPWindowTypeDesktop;
+			}
+			else if(windowType[n] == _net_wm_window_type_normal)
+			{
+				_windowType = FPWindowTypeNormal;
+			}
+			else if(windowType[n] == _net_wm_window_type_utility)
+			{
+				_windowType = FPWindowTypeUtility;
+			}
+			else if(windowType[n] == _net_wm_window_type_splash)
+			{
+				_windowType = FPWindowTypeSplash;
+			}
+			else if(windowType[n] == _net_wm_window_type_tooltip)
+			{
+				_windowType = FPWindowTypeTooltip;
+			}
+			else if(windowType[n] == _net_wm_window_type_dialog)
+			{
+				_windowType = FPWindowTypeDialog;
+			}	
+		}
+		XFree(windowType);
+		//usleep(1 * 1000 * 1000);
+	}
 }
 -(void)handleXEvent:(XEvent)event;
 {
 {
 	FPX11Display * mainDisplay = [FPX11Display mainDisplay];
 
-	//XWindowAttributes winAttr;
+	BOOL shouldResize = YES;
+	BOOL shouldCenter = YES;
+	switch(_windowType)
+	{
+		case FPWindowTypeMenu:
+		case FPWindowTypeDropdownMenu:
+		case FPWindowTypeTooltip:
+		shouldResize = NO;
+		shouldCenter = NO;
+		break;
+		case FPWindowTypeDialog:
+		shouldResize = NO;
+		shouldCenter = YES;
+		break;
+
+		default:
+		shouldResize = YES;
+		shouldCenter = YES;
+	}
+
 	XSizeHints sizeHints;
 	long userSuppliedHints;
 	int hasMinSize = 0, hasMaxSize = 0, hasIncrement = 0;
 
-	/* Get window attributes */
-	//XGetWindowAttributes([mainDisplay display], _window, &winAttr);
-
 	/* Get size hints for the window */
 	XGetWMNormalHints([mainDisplay display], _window, &sizeHints, &userSuppliedHints);
 	if (sizeHints.flags & PMinSize)
 	if (sizeHints.flags & PResizeInc)
 		hasIncrement = 1;
 
-	float newW = [mainDisplay widthForScreen:[mainDisplay screen]];
-	float newH = [mainDisplay heightForScreen:[mainDisplay screen]];
+	float screenW = [mainDisplay widthForScreen:[mainDisplay screen]];
+	float screenH = [mainDisplay heightForScreen:[mainDisplay screen]];
+	float newW = screenW;
+	float newH = screenH;
 	if(hasMaxSize)
 	{
 		NSLog(@"MaxW: %d, MaxH: %d", sizeHints.max_width, sizeHints.max_height);
 	}
 
 	// TODO: center
-	XMoveResizeWindow([mainDisplay display], _window, 0, 0, newW, newH);
-
+	if(shouldCenter && shouldResize)
+		XMoveResizeWindow([mainDisplay display], _window, screenW/2 - newW / 2, screenH/2 - newH / 2, newW, newH);
+	else if (shouldCenter)
+		XMoveWindow([mainDisplay display], _window, screenW/2 - newW/2, screenH / 2 - newH / 2);
+	else if (shouldResize)
+		XResizeWindow([mainDisplay display], _window, newW, newH);
 	// it is expected that, at this point, someone will
 	// free resources, collect attributes, and build resources.
 
 	SWITCH_TO_STAGE_CONTEXT;
 #endif
 
+#if OPTIMIZED_TEXTURE_BUILD
+	glBindTexture(_textureTarget, _texture);
+#else
 	[self bindTexture];
+#endif
+
 #if SWITCH_CONTEXTS
 	SWITCH_TO_STAGE_CONTEXT;
 #endif
 #if 1
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix ();
+		glTranslatef (_x, _y, _z);
 		
 		/////
 
 
 		////
 
-		glTranslatef (_x, _y, _z);
 		/*
 		extent_clip (0, 0, mirror->w, mirror->h);
 		*/
 
 		glLineWidth(4);		
 		glDisable(_textureTarget);
-		glColor4f(1,0.5+sin(_timeAlive*3)/2,1,1);
+		switch(_windowType)
+		{
+			case FPWindowTypeNormal:
+			glColor4f(1,0.5+sin(_timeAlive*3)/2,1,1);
+			break;
+			case FPWindowTypeUtility:
+			glColor4f(1,0.5+sin(_timeAlive*3)/2,0.5+sin(_timeAlive*3)/2,1);
+			break;
+			case FPWindowTypeMenu:
+			case FPWindowTypeDropdownMenu:
+			glColor4f(0,0.5+sin(_timeAlive*3)/2,0,1);
+			break;
+			case FPWindowTypeTooltip:
+			glColor4f(0.5 + sin(_timeAlive*3),0.5+sin(_timeAlive*3)/2,0.3,1);
+			break;
+			case FPWindowTypeDialog:
+			glColor4f(0.5+sin(_timeAlive*3)/2,1,0.5+sin(_timeAlive*3)/2,1);
+			break;
+			
+			default:
+			glColor4f(0,0,0,1);
+			break;
+		}
 		glBegin(GL_LINE_LOOP);
 		glVertex2f(0,0);
 		glVertex2f(0,_height);
 #endif
 	
 	glDisable(_textureTarget);
+#if OPTIMIZED_TEXTURE_BUILD
+	glBindTexture(_textureTarget, 0);
+#else
 	[self unbindTexture];
+#endif
 
 	glXWaitGL();
 #if SWITCH_CONTEXTS