aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/unix
diff options
context:
space:
mode:
Diffstat (limited to 'src/libui_sdl/libui/unix')
-rw-r--r--src/libui_sdl/libui/unix/CMakeLists.txt2
-rw-r--r--src/libui_sdl/libui/unix/area.c116
-rw-r--r--src/libui_sdl/libui/unix/draw.c4
-rw-r--r--src/libui_sdl/libui/unix/gl.c246
-rw-r--r--src/libui_sdl/libui/unix/main.c24
-rw-r--r--src/libui_sdl/libui/unix/uipriv_unix.h8
-rw-r--r--src/libui_sdl/libui/unix/window.c18
7 files changed, 402 insertions, 16 deletions
diff --git a/src/libui_sdl/libui/unix/CMakeLists.txt b/src/libui_sdl/libui/unix/CMakeLists.txt
index 9300bcb..c69081e 100644
--- a/src/libui_sdl/libui/unix/CMakeLists.txt
+++ b/src/libui_sdl/libui/unix/CMakeLists.txt
@@ -43,6 +43,7 @@ list(APPEND _LIBUI_SOURCES
unix/text.c
unix/util.c
unix/window.c
+ unix/gl.c
)
set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE)
@@ -62,6 +63,7 @@ macro(_handle_static)
set(_oname libui-combined.o)
add_custom_command(
OUTPUT ${_oname}
+ DEPENDS ${_LIBUINAME}
COMMAND
ld -r --whole-archive ${_aname} -o ${_oname}
COMMAND
diff --git a/src/libui_sdl/libui/unix/area.c b/src/libui_sdl/libui/unix/area.c
index 2da9bab..5734b4b 100644
--- a/src/libui_sdl/libui/unix/area.c
+++ b/src/libui_sdl/libui/unix/area.c
@@ -28,6 +28,8 @@ struct areaWidgetClass {
GtkDrawingAreaClass parent_class;
};
+typedef struct uiGLContext uiGLContext;
+
struct uiArea {
uiUnixControl c;
GtkWidget *widget; // either swidget or areaWidget depending on whether it is scrolling
@@ -39,6 +41,10 @@ struct uiArea {
GtkWidget *areaWidget;
GtkDrawingArea *drawingArea;
areaWidget *area;
+
+ gboolean opengl;
+ uiGLContext *glContext;
+ unsigned int* req_versions;
int bgR, bgG, bgB;
@@ -57,6 +63,21 @@ struct uiArea {
G_DEFINE_TYPE(areaWidget, areaWidget, GTK_TYPE_DRAWING_AREA)
+int boub(GtkWidget* w) { return isAreaWidget(w); }
+void baba(GtkWidget* w)
+{
+ if (!isAreaWidget(w)) return;
+
+ areaWidget *aw = areaWidget(w);
+ uiArea *a = aw->a;
+ if (!a->opengl) return;
+
+ GdkGLContext* oldctx = gdk_gl_context_get_current();
+ uiGLMakeContextCurrent(a->glContext);
+ glFinish();
+ gdk_gl_context_make_current(oldctx);
+}
+
static void areaWidget_init(areaWidget *aw)
{
// for events
@@ -133,21 +154,28 @@ static gboolean areaWidget_draw(GtkWidget *w, cairo_t *cr)
loadAreaSize(a, &(dp.AreaWidth), &(dp.AreaHeight));
- cairo_clip_extents(cr, &clipX0, &clipY0, &clipX1, &clipY1);
- dp.ClipX = clipX0;
- dp.ClipY = clipY0;
- dp.ClipWidth = clipX1 - clipX0;
- dp.ClipHeight = clipY1 - clipY0;
-
- if (a->bgR != -1)
+ if (!a->opengl)
+ {
+ cairo_clip_extents(cr, &clipX0, &clipY0, &clipX1, &clipY1);
+ dp.ClipX = clipX0;
+ dp.ClipY = clipY0;
+ dp.ClipWidth = clipX1 - clipX0;
+ dp.ClipHeight = clipY1 - clipY0;
+
+ if (a->bgR != -1)
+ {
+ cairo_set_source_rgb(cr, a->bgR/255.0, a->bgG/255.0, a->bgB/255.0);
+ cairo_paint(cr);
+ }
+
+ // no need to save or restore the graphics state to reset transformations; GTK+ does that for us
+ (*(a->ah->Draw))(a->ah, a, &dp);
+ }
+ else
{
- cairo_set_source_rgb(cr, a->bgR/255.0, a->bgG/255.0, a->bgB/255.0);
- cairo_paint(cr);
+ areaDrawGL(w, &dp, cr, a->glContext);
}
- // no need to save or restore the graphics state to reset transformations; GTK+ does that for us
- (*(a->ah->Draw))(a->ah, a, &dp);
-
freeContext(dp.Context);
return FALSE;
}
@@ -598,7 +626,15 @@ static void areaWidget_class_init(areaWidgetClass *class)
// control implementation
-uiUnixControlAllDefaults(uiArea)
+uiUnixControlAllDefaultsExceptDestroy(uiArea)
+
+static void uiAreaDestroy(uiControl *c)
+{
+ uiArea* a = uiArea(c);
+ if (a->opengl && a->glContext) freeGLContext(a->glContext);
+ g_object_unref(uiArea(c)->widget);
+ uiFreeControl(c);
+}
void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b)
{
@@ -716,6 +752,7 @@ uiArea *uiNewArea(uiAreaHandler *ah)
a->ah = ah;
a->scrolling = FALSE;
+ a->opengl = FALSE;
a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType,
"libui-area", a,
@@ -730,6 +767,58 @@ uiArea *uiNewArea(uiAreaHandler *ah)
return a;
}
+void _areaCreateGLContext(GtkWidget* widget, gpointer data)
+{
+ uiArea* a = (uiArea*)data;
+
+ uiGLContext* ctx = NULL;
+ for (int i = 0; a->req_versions[i] && !ctx; i++)
+ {
+ int major = uiGLVerMajor(a->req_versions[i]);
+ int minor = uiGLVerMinor(a->req_versions[i]);
+
+ // we cannot support any version older than 3.2 via GDK
+ if ((major < 3) || (major == 3 && minor < 2))
+ break;
+
+ ctx = createGLContext(widget, major, minor);
+ }
+
+ a->glContext = ctx;
+}
+
+uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions)
+{
+ uiArea *a;
+
+ uiUnixNewControl(uiArea, a);
+
+ a->ah = ah;
+ a->scrolling = FALSE;
+ a->opengl = TRUE;
+
+ a->glContext = NULL;
+ a->req_versions = req_versions;
+ a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType,
+ "libui-area", a,
+ NULL));
+ a->area = areaWidget(a->areaWidget);
+
+ a->widget = a->areaWidget;
+
+ g_signal_connect(a->widget, "realize", G_CALLBACK(_areaCreateGLContext), a);
+
+ uiAreaSetBackgroundColor(a, -1, -1, -1);
+
+ return a;
+}
+
+uiGLContext *uiAreaGetGLContext(uiArea* a)
+{
+ if (!a) return NULL;
+ return a->glContext;
+}
+
uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
{
uiArea *a;
@@ -740,6 +829,7 @@ uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
a->scrolling = TRUE;
a->scrollWidth = width;
a->scrollHeight = height;
+ a->opengl = FALSE;
a->swidget = gtk_scrolled_window_new(NULL, NULL);
a->scontainer = GTK_CONTAINER(a->swidget);
diff --git a/src/libui_sdl/libui/unix/draw.c b/src/libui_sdl/libui/unix/draw.c
index e55397e..5befcd3 100644
--- a/src/libui_sdl/libui/unix/draw.c
+++ b/src/libui_sdl/libui/unix/draw.c
@@ -143,13 +143,13 @@ void uiDrawRestore(uiDrawContext *c)
// bitmap API
-uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
+uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha)
{
uiDrawBitmap* bmp;
bmp = uiNew(uiDrawBitmap);
- bmp->bmp = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
+ bmp->bmp = cairo_image_surface_create(alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, width, height);
if (cairo_surface_status(bmp->bmp) != CAIRO_STATUS_SUCCESS)
implbug("error creating bitmap: %s",
cairo_status_to_string(cairo_surface_status(bmp->bmp)));
diff --git a/src/libui_sdl/libui/unix/gl.c b/src/libui_sdl/libui/unix/gl.c
new file mode 100644
index 0000000..e1665ee
--- /dev/null
+++ b/src/libui_sdl/libui/unix/gl.c
@@ -0,0 +1,246 @@
+// 26 may 2019
+#include "uipriv_unix.h"
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <EGL/egl.h>
+
+extern GThread* gtkthread;
+extern GMutex glmutex;
+
+struct uiGLContext
+{
+ GtkWidget* widget;
+ GdkWindow* window;
+
+ GdkGLContext *gctx;
+ int vermaj, vermin;
+
+ int width, height;
+ int scale;
+ GLuint renderbuffer[2][2];
+ GLuint framebuffer[2];
+ int backbuffer;
+};
+
+static void areaAllocRenderbuffer(uiGLContext* glctx);
+
+static PFNGLGENRENDERBUFFERSPROC _glGenRenderbuffers;
+static PFNGLDELETERENDERBUFFERSPROC _glDeleteRenderbuffers;
+static PFNGLBINDRENDERBUFFERPROC _glBindRenderbuffer;
+static PFNGLRENDERBUFFERSTORAGEPROC _glRenderbufferStorage;
+static PFNGLGETRENDERBUFFERPARAMETERIVPROC _glGetRenderbufferParameteriv;
+
+static PFNGLGENRENDERBUFFERSPROC _glGenFramebuffers;
+static PFNGLDELETERENDERBUFFERSPROC _glDeleteFramebuffers;
+static PFNGLBINDRENDERBUFFERPROC _glBindFramebuffer;
+static PFNGLFRAMEBUFFERTEXTUREPROC _glFramebufferTexture;
+static PFNGLFRAMEBUFFERRENDERBUFFERPROC _glFramebufferRenderbuffer;
+static PFNGLCHECKFRAMEBUFFERSTATUSPROC _glCheckFramebufferStatus;
+
+static int _procsLoaded = 0;
+
+static void _loadGLProcs(GdkGLContext* glctx)
+{
+ if (_procsLoaded) return;
+
+ _glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)uiGLGetProcAddress("glGenRenderbuffers");
+ _glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)uiGLGetProcAddress("glDeleteRenderbuffers");
+ _glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)uiGLGetProcAddress("glBindRenderbuffer");
+ _glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)uiGLGetProcAddress("glRenderbufferStorage");
+ _glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)uiGLGetProcAddress("glGetRenderbufferParameteriv");
+
+ _glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)uiGLGetProcAddress("glGenFramebuffers");
+ _glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)uiGLGetProcAddress("glDeleteFramebuffers");
+ _glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)uiGLGetProcAddress("glBindFramebuffer");
+ _glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)uiGLGetProcAddress("glFramebufferTexture");
+ _glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)uiGLGetProcAddress("glFramebufferRenderbuffer");
+ _glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)uiGLGetProcAddress("glCheckFramebufferStatus");
+
+ _procsLoaded = 1;
+}
+
+uiGLContext *createGLContext(GtkWidget* widget, int maj, int min)
+{
+ GdkWindow* gdkwin = gtk_widget_get_window(widget);
+
+ GError* err = NULL;
+ GdkGLContext* gctx = gdk_window_create_gl_context(gdkwin, &err);
+ if (err != NULL || gctx == NULL)
+ {
+ return NULL;
+ }
+
+ // TODO: make the set_use_es call conditional (#ifdef or smth) for older versions of gdk?
+ gdk_gl_context_set_use_es(gctx, FALSE);
+ gdk_gl_context_set_required_version(gctx, maj, min);
+
+ gboolean res = gdk_gl_context_realize(gctx, &err);
+ if (err != NULL || res == FALSE)
+ {
+ return NULL;
+ }
+
+ uiGLContext* ctx = uiNew(uiGLContext);
+
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ int window_scale = gdk_window_get_scale_factor(gdkwin);
+ ctx->width = allocation.width;
+ ctx->height = allocation.height;
+ ctx->scale = window_scale;
+
+ gdk_gl_context_make_current(gctx);
+ _loadGLProcs(gctx);
+ areaAllocRenderbuffer(ctx);
+ ctx->backbuffer = 0;
+
+ ctx->widget = widget;
+ ctx->window = gdkwin;
+ ctx->gctx = gctx;
+
+ return ctx;
+}
+
+void freeGLContext(uiGLContext* glctx)
+{
+ if (glctx == NULL) return;
+
+ gdk_gl_context_make_current(glctx->gctx);
+ _glDeleteRenderbuffers(4, &glctx->renderbuffer[0][0]);
+ _glDeleteFramebuffers(2, &glctx->framebuffer[0]);
+
+ gdk_gl_context_clear_current();
+ g_object_unref(glctx->gctx);
+ uiFree(glctx);
+}
+
+static void areaAllocRenderbuffer(uiGLContext* glctx)
+{
+ // TODO: create textures as a fallback if GL_RGB renderbuffer isn't supported?
+ // they say GL implementations aren't required to support a GL_RGB renderbuffer
+ // however, a GL_RGBA one would cause gdk_cairo_draw_from_gl() to fall back to glReadPixels()
+
+ _glGenRenderbuffers(4, &glctx->renderbuffer[0][0]);
+ _glGenFramebuffers(2, &glctx->framebuffer[0]);
+
+ _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][0]);
+ _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
+ //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][1]);
+ //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
+
+ _glBindFramebuffer(GL_FRAMEBUFFER, glctx->framebuffer[0]);
+ _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glctx->renderbuffer[0][0]);
+ _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, glctx->renderbuffer[0][1]);
+
+ _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][0]);
+ _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
+ //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][1]);
+ //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
+
+ _glBindFramebuffer(GL_FRAMEBUFFER, glctx->framebuffer[1]);
+ _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glctx->renderbuffer[1][0]);
+ _glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, glctx->renderbuffer[1][1]);
+
+ //if (_glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ // printf("FRAMEBUFFER IS BAD!! %04X\n", _glCheckFramebufferStatus(GL_FRAMEBUFFER));
+}
+
+static void areaReallocRenderbuffer(uiGLContext* glctx)
+{
+ _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][0]);
+ _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
+ //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][1]);
+ //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
+
+ _glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][0]);
+ _glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
+ //_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][1]);
+ //_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
+}
+
+void areaDrawGL(GtkWidget* widget, uiAreaDrawParams* dp, cairo_t* cr, uiGLContext* glctx)
+{
+ int window_scale = gdk_window_get_scale_factor(glctx->window);
+
+ if (glctx->width != dp->AreaWidth || glctx->height != dp->AreaHeight || glctx->scale != window_scale)
+ {
+ glctx->width = dp->AreaWidth;
+ glctx->height = dp->AreaHeight;
+ glctx->scale = window_scale;
+ areaReallocRenderbuffer(glctx);
+ }
+ else
+ {
+ gdk_cairo_draw_from_gl(cr, gtk_widget_get_window(widget),
+ glctx->renderbuffer[glctx->backbuffer][0], GL_RENDERBUFFER,
+ 1, 0, 0, glctx->width*glctx->scale, glctx->height*glctx->scale);
+ }
+}
+
+int uiGLGetFramebuffer(uiGLContext* ctx)
+{
+ return ctx->framebuffer[ctx->backbuffer];
+}
+
+float uiGLGetFramebufferScale(uiGLContext* ctx)
+{
+ return (float)ctx->scale;
+}
+
+void uiGLSwapBuffers(uiGLContext* ctx)
+{
+ ctx->backbuffer = ctx->backbuffer ? 0 : 1;
+}
+
+void uiGLMakeContextCurrent(uiGLContext* ctx)
+{
+ if (!ctx)
+ {
+ gdk_gl_context_clear_current();
+ return;
+ }
+
+ if (ctx->gctx == gdk_gl_context_get_current()) return;
+ gdk_gl_context_make_current(ctx->gctx);
+}
+
+void uiGLBegin(uiGLContext* ctx)
+{
+ if (g_thread_self() != gtkthread)
+ {
+ g_mutex_lock(&glmutex);
+ }
+}
+
+void uiGLEnd(uiGLContext* ctx)
+{
+ if (g_thread_self() != gtkthread)
+ {
+ g_mutex_unlock(&glmutex);
+ }
+}
+
+void *uiGLGetProcAddress(const char* proc)
+{
+ // TODO: consider using epoxy or something funny
+
+ void* ptr;
+
+ ptr = glXGetProcAddressARB((const GLubyte*)proc);
+ if (ptr) return ptr;
+
+ ptr = eglGetProcAddress(proc);
+ if (ptr) return ptr;
+
+ ptr = dlsym(NULL /* RTLD_DEFAULT */, proc);
+ if (ptr) return ptr;
+
+ return NULL;
+}
+unsigned int uiGLGetVersion(uiGLContext* ctx)
+{
+ if (!ctx) return 0;
+ return uiGLVersion(ctx->vermaj, ctx->vermin);
+}
+
diff --git a/src/libui_sdl/libui/unix/main.c b/src/libui_sdl/libui/unix/main.c
index 409b659..516bd76 100644
--- a/src/libui_sdl/libui/unix/main.c
+++ b/src/libui_sdl/libui/unix/main.c
@@ -5,6 +5,25 @@ uiInitOptions options;
// kind of a hack
GThread* gtkthread;
+GMutex glmutex;
+
+static void _eventfilter(GdkEvent* evt, gpointer data)
+{
+ if (evt->type == GDK_EXPOSE)
+ {
+ g_mutex_lock(&glmutex);
+ gtk_main_do_event(evt);
+ g_mutex_unlock(&glmutex);
+ return;
+ }
+
+ gtk_main_do_event(evt);
+}
+
+static void _eventfilterdestroy(gpointer data)
+{
+ printf("DELET\n");
+}
const char *uiInit(uiInitOptions *o)
{
@@ -21,6 +40,7 @@ const char *uiInit(uiInitOptions *o)
loadFutures();
gtkthread = g_thread_self();
+ g_mutex_init(&glmutex);
GList* iconlist = NULL;
iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_16x16.png", NULL));
@@ -31,6 +51,10 @@ const char *uiInit(uiInitOptions *o)
gtk_window_set_default_icon_list(iconlist);
+ g_mutex_init(&glmutex);
+
+ gdk_event_handler_set(_eventfilter, NULL, _eventfilterdestroy);
+
return NULL;
}
diff --git a/src/libui_sdl/libui/unix/uipriv_unix.h b/src/libui_sdl/libui/unix/uipriv_unix.h
index 33ff1e3..9b77188 100644
--- a/src/libui_sdl/libui/unix/uipriv_unix.h
+++ b/src/libui_sdl/libui/unix/uipriv_unix.h
@@ -5,7 +5,7 @@
#define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_10
#include <gtk/gtk.h>
#include <math.h>
-#include <dlfcn.h> // see drawtext.c
+#include <dlfcn.h> // see drawtext.c, gl.c
#include <langinfo.h>
#include <string.h>
#include <stdlib.h>
@@ -63,3 +63,9 @@ extern GtkCellRenderer *newCellRendererButton(void);
extern void loadFutures(void);
extern PangoAttribute *FUTURE_pango_attr_foreground_alpha_new(guint16 alpha);
extern gboolean FUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, gint pos, const char *name);
+
+// gl.c
+extern uiGLContext *createGLContext(GtkWidget* widget, int maj, int min);
+extern void freeGLContext(uiGLContext* glctx);
+extern void areaDrawGL(GtkWidget* widget, uiAreaDrawParams* dp, cairo_t* cr, uiGLContext* glctx);
+
diff --git a/src/libui_sdl/libui/unix/window.c b/src/libui_sdl/libui/unix/window.c
index 7da1134..6d5e2de 100644
--- a/src/libui_sdl/libui/unix/window.c
+++ b/src/libui_sdl/libui/unix/window.c
@@ -102,6 +102,23 @@ static void uiWindowDestroy(uiControl *c)
uiFreeControl(uiControl(w));
}
+void uiWindowSetPosition(uiWindow *w, int x, int y)
+{
+ if (!w) return;
+
+ gtk_window_move(w->window, x, y);
+}
+
+void uiWindowPosition(uiWindow *w, int *x, int *y)
+{
+ if (!w) return;
+
+ int xx, yy;
+ gtk_window_get_position(w->window, &xx, &yy);
+ if (x) *x = xx;
+ if (y) *y = yy;
+}
+
uiUnixControlDefaultHandle(uiWindow)
uiControl *uiWindowParent(uiControl *c)
@@ -442,3 +459,4 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, i
return w;
}
+