blob: 3c1703b71c0542ecf4cc0dd13b0ea9a0ee02591e [file] [log] [blame]
/*
* Copyright © 2010-2011 Linaro Limited
* Copyright © 2013 Canonical Ltd
*
* This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
*
* glmark2 is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* glmark2. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexandros Frantzis
*/
#include "native-state-x11.h"
#include "log.h"
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
/******************
* Public methods *
******************/
NativeStateX11::~NativeStateX11()
{
if (xdpy_)
{
if (xwin_)
XDestroyWindow(xdpy_, xwin_);
XCloseDisplay(xdpy_);
}
}
bool
NativeStateX11::init_display()
{
if (!xdpy_)
xdpy_ = XOpenDisplay(NULL);
return (xdpy_ != 0);
}
void*
NativeStateX11::display()
{
return (void*)xdpy_;
}
bool
NativeStateX11::create_window(WindowProperties const& properties)
{
static const char *win_name("glmark2 " GLMARK_VERSION);
if (!xdpy_) {
Log::error("Error: X11 Display has not been initialized!\n");
return false;
}
/* Recreate an existing window only if it has actually been resized */
if (xwin_) {
if (properties_.fullscreen != properties.fullscreen ||
(properties.fullscreen == false &&
(properties_.width != properties.width ||
properties_.height != properties.height)))
{
XDestroyWindow(xdpy_, xwin_);
xwin_ = 0;
}
else
{
return true;
}
}
/* Set desired attributes */
properties_.fullscreen = properties.fullscreen;
properties_.visual_id = properties.visual_id;
if (properties_.fullscreen) {
/* Get the screen (root window) size */
XWindowAttributes window_attr;
XGetWindowAttributes(xdpy_, RootWindow(xdpy_, DefaultScreen(xdpy_)),
&window_attr);
properties_.width = window_attr.width;
properties_.height = window_attr.height;
}
else {
properties_.width = properties.width;
properties_.height = properties.height;
}
XVisualInfo vis_tmpl;
XVisualInfo *vis_info = 0;
int num_visuals;
/* The X window visual must match the supplied visual id */
vis_tmpl.visualid = properties_.visual_id;
vis_info = XGetVisualInfo(xdpy_, VisualIDMask, &vis_tmpl,
&num_visuals);
if (!vis_info) {
Log::error("Error: Could not get a valid XVisualInfo!\n");
return false;
}
Log::debug("Creating XWindow W: %d H: %d VisualID: 0x%x\n",
properties_.width, properties_.height, vis_info->visualid);
/* window attributes */
XSetWindowAttributes attr;
unsigned long mask;
Window root = RootWindow(xdpy_, DefaultScreen(xdpy_));
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(xdpy_, root, vis_info->visual, AllocNone);
attr.event_mask = KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
xwin_ = XCreateWindow(xdpy_, root, 0, 0, properties_.width, properties_.height,
0, vis_info->depth, InputOutput,
vis_info->visual, mask, &attr);
XFree(vis_info);
if (!xwin_) {
Log::error("Error: XCreateWindow() failed!\n");
return false;
}
/* set hints and properties */
Atom fs_atom = None;
if (properties_.fullscreen) {
fs_atom = XInternAtom(xdpy_, "_NET_WM_STATE_FULLSCREEN", True);
if (fs_atom == None)
Log::debug("Warning: Could not set EWMH Fullscreen hint.\n");
}
if (fs_atom != None) {
XChangeProperty(xdpy_, xwin_,
XInternAtom(xdpy_, "_NET_WM_STATE", True),
XA_ATOM, 32, PropModeReplace,
reinterpret_cast<unsigned char*>(&fs_atom), 1);
}
else {
XSizeHints sizehints;
sizehints.min_width = properties_.width;
sizehints.min_height = properties_.height;
sizehints.max_width = properties_.width;
sizehints.max_height = properties_.height;
sizehints.flags = PMaxSize | PMinSize;
XSetWMProperties(xdpy_, xwin_, NULL, NULL,
NULL, 0, &sizehints, NULL, NULL);
}
/* Set the window name */
XStoreName(xdpy_ , xwin_, win_name);
/* Gracefully handle Window Delete event from window manager */
Atom wmDelete = XInternAtom(xdpy_, "WM_DELETE_WINDOW", True);
XSetWMProtocols(xdpy_, xwin_, &wmDelete, 1);
return true;
}
void*
NativeStateX11::window(WindowProperties& properties)
{
properties = properties_;
return (void*)xwin_;
}
void
NativeStateX11::visible(bool visible)
{
if (visible)
XMapWindow(xdpy_, xwin_);
}
bool
NativeStateX11::should_quit()
{
XEvent event;
if (!XPending(xdpy_))
return false;
XNextEvent(xdpy_, &event);
if (event.type == KeyPress) {
if (XLookupKeysym(&event.xkey, 0) == XK_Escape)
return true;
}
else if (event.type == ClientMessage) {
/* Window Delete event from window manager */
return true;
}
return false;
}