Merge pull request #3 from andlabs/master

Merge upstream changes
This commit is contained in:
emersion 2016-06-16 14:48:11 +02:00 committed by GitHub
commit 1fa79fd3b6
10 changed files with 508 additions and 16 deletions

View File

@ -16,10 +16,14 @@ This README is being written.<br>
## Updates
*Note that today's entry may be updated later today Eastern Time.*
*Note that today's entry (Eastern Time) may be updated later today.*
* **16 June 2016**
* Added `uiWindowContentSize()`, `uiWindowSetContentSize()`, and `uiWindowOnContentSizeChanged()` methods for manipulating uiWindow content sizes. Note the use of "content size"; the size you work with does NOT include window decorations (titlebars, menus, etc.).
* **15 June 2016**
* Added `uiFormDelete()`; thanks to @emersion.
* Added `uiWindowPosition()`, `uiWindowSetPosition()`, `uiWindowCenter()`, and `uiWindowOnPositionChanged()`, methods for manipulating uiWindow position.
* **14 June 2016**
* uiDarwinControl now has a `ChildVisibilityChanged()` method and a corresponding `NotifyVisibilityChanged()` function that is called by the default show/hide handlers. This is used to make visibility changes work on OS X; uiBox, uiForm, and uiGrid all respect these now.

View File

@ -9,12 +9,20 @@ struct uiWindow {
int (*onClosing)(uiWindow *, void *);
void *onClosingData;
struct singleChildConstraints constraints;
void (*onPositionChanged)(uiWindow *, void *);
void *onPositionChangedData;
BOOL suppressPositionChanged;
void (*onContentSizeChanged)(uiWindow *, void *);
void *onContentSizeChangedData;
BOOL suppressSizeChanged;
};
@interface windowDelegateClass : NSObject<NSWindowDelegate> {
struct mapTable *windows;
}
- (BOOL)windowShouldClose:(id)sender;
- (void)windowDidMove:(NSNotification *)note;
- (void)windowDidResize:(NSNotification *)note;
- (void)registerWindow:(uiWindow *)w;
- (void)unregisterWindow:(uiWindow *)w;
- (uiWindow *)lookupWindow:(NSWindow *)w;
@ -47,6 +55,25 @@ struct uiWindow {
return NO;
}
// TODO doesn't happen live
- (void)windowDidMove:(NSNotification *)note
{
uiWindow *w;
w = [self lookupWindow:((NSWindow *) [note object])];
if (!w->suppressPositionChanged)
(*(w->onPositionChanged))(w, w->onPositionChangedData);
}
- (void)windowDidResize:(NSNotification *)note
{
uiWindow *w;
w = [self lookupWindow:((NSWindow *) [note object])];
if (!w->suppressSizeChanged)
(*(w->onContentSizeChanged))(w, w->onContentSizeChangedData);
}
- (void)registerWindow:(uiWindow *)w
{
mapSet(self->windows, w->window, w);
@ -204,6 +231,71 @@ void uiWindowSetTitle(uiWindow *w, const char *title)
[w->window setTitle:toNSString(title)];
}
void uiWindowPosition(uiWindow *w, int *x, int *y)
{
NSScreen *screen;
NSRect r;
r = [w->window frame];
*x = r.origin.x;
// this is the right screen to use; thanks mikeash in irc.freenode.net/#macdev
// -mainScreen is useless for positioning (it's just the key window's screen)
// and we use -frame, not -visibleFrame, for dealing with absolute positions
screen = (NSScreen *) [[NSScreen screens] objectAtIndex:0];
*y = ([screen frame].size.height - r.origin.y) - r.size.height;
}
void uiWindowSetPosition(uiWindow *w, int x, int y)
{
// -[NSWindow setFrameTopLeftPoint:] is acting weird so...
NSRect r;
NSScreen *screen;
// this fires windowDidMove:
w->suppressPositionChanged = YES;
r = [w->window frame];
r.origin.x = x;
screen = (NSScreen *) [[NSScreen screens] objectAtIndex:0];
r.origin.y = [screen frame].size.height - (y + r.size.height);
[w->window setFrameOrigin:r.origin];
w->suppressPositionChanged = NO;
}
void uiWindowCenter(uiWindow *w)
{
w->suppressPositionChanged = YES;
[w->window center];
w->suppressPositionChanged = NO;
}
void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onPositionChanged = f;
w->onPositionChangedData = data;
}
void uiWindowContentSize(uiWindow *w, int *width, int *height)
{
NSRect r;
r = [w->window contentRectForFrameRect:[w->window frame]];
*width = r.size.width;
*height = r.size.height;
}
void uiWindowSetContentSize(uiWindow *w, int width, int height)
{
w->suppressSizeChanged = YES;
[w->window setContentSize:NSMakeSize(width, height)];
w->suppressSizeChanged = NO;
}
void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onContentSizeChanged = f;
w->onContentSizeChangedData = data;
}
void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
w->onClosing = f;
@ -245,6 +337,11 @@ static int defaultOnClosing(uiWindow *w, void *data)
return 0;
}
static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data)
{
// do nothing
}
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
{
uiWindow *w;
@ -269,6 +366,8 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
}
[windowDelegate registerWindow:w];
uiWindowOnClosing(w, defaultOnClosing, NULL);
uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL);
uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL);
return w;
}

3
doc/windowmovesize Normal file
View File

@ -0,0 +1,3 @@
you should never need to use these functions
they are provided only for the cases when ABSOLUTELY NECESSARY
the operating system may ignore your requests, for instance, if you are giving it invalid numbers or a size too small to fit; this is all system-defined

View File

@ -25,6 +25,7 @@ _add_exec(tester
page12.c
page13.c
page14.c
page15.c
spaced.c
${_TEST_RESOURCES_RC}
)

View File

@ -49,6 +49,7 @@ int main(int argc, char *argv[])
uiBox *page6, *page7, *page8, *page9, *page10;
uiBox *page11, *page12, *page13;
uiTab *page14;
uiBox *page15;
uiTab *outerTab;
uiTab *innerTab;
int nomenus = 0;
@ -148,6 +149,9 @@ int main(int argc, char *argv[])
page14 = makePage14();
uiTabAppend(innerTab, "Page 14", uiControl(page14));
page15 = makePage15(w);
uiTabAppend(innerTab, "Page 15", uiControl(page15));
if (startspaced)
setSpaced(1);

129
test/page15.c Normal file
View File

@ -0,0 +1,129 @@
// 15 june 2016
#include "test.h"
static uiSpinbox *x, *y;
static uiSpinbox *width, *height;
static void moveX(uiSpinbox *s, void *data)
{
uiWindow *w = uiWindow(data);
int xp, yp;
uiWindowPosition(w, &xp, &yp);
xp = uiSpinboxValue(x);
uiWindowSetPosition(w, xp, yp);
}
static void moveY(uiSpinbox *s, void *data)
{
uiWindow *w = uiWindow(data);
int xp, yp;
uiWindowPosition(w, &xp, &yp);
yp = uiSpinboxValue(y);
uiWindowSetPosition(w, xp, yp);
}
static void updatepos(uiWindow *w)
{
int xp, yp;
uiWindowPosition(w, &xp, &yp);
uiSpinboxSetValue(x, xp);
uiSpinboxSetValue(y, yp);
}
static void center(uiButton *b, void *data)
{
uiWindow *w = uiWindow(data);
uiWindowCenter(w);
updatepos(w);
}
void onMove(uiWindow *w, void *data)
{
printf("move\n");
updatepos(w);
}
static void sizeWidth(uiSpinbox *s, void *data)
{
uiWindow *w = uiWindow(data);
int xp, yp;
uiWindowContentSize(w, &xp, &yp);
xp = uiSpinboxValue(width);
uiWindowSetContentSize(w, xp, yp);
}
static void sizeHeight(uiSpinbox *s, void *data)
{
uiWindow *w = uiWindow(data);
int xp, yp;
uiWindowContentSize(w, &xp, &yp);
yp = uiSpinboxValue(height);
uiWindowSetContentSize(w, xp, yp);
}
static void updatesize(uiWindow *w)
{
int xp, yp;
uiWindowContentSize(w, &xp, &yp);
uiSpinboxSetValue(width, xp);
uiSpinboxSetValue(height, yp);
}
void onSize(uiWindow *w, void *data)
{
printf("size\n");
updatesize(w);
}
uiBox *makePage15(uiWindow *w)
{
uiBox *page15;
uiBox *hbox;
uiButton *button;
page15 = newVerticalBox();
hbox = newHorizontalBox();
// TODO if I make this 1 and not add anything else AND not call uiWindowOnPositionChanged(), on OS X the box won't be able to grow vertically
uiBoxAppend(page15, uiControl(hbox), 0);
uiBoxAppend(hbox, uiControl(uiNewLabel("Position")), 0);
x = uiNewSpinbox(INT_MIN, INT_MAX);
uiBoxAppend(hbox, uiControl(x), 1);
y = uiNewSpinbox(INT_MIN, INT_MAX);
uiBoxAppend(hbox, uiControl(y), 1);
button = uiNewButton("Center");
uiBoxAppend(hbox, uiControl(button), 0);
uiSpinboxOnChanged(x, moveX, w);
uiSpinboxOnChanged(y, moveY, w);
uiButtonOnClicked(button, center, w);
uiWindowOnPositionChanged(w, onMove, NULL);
updatepos(w);
hbox = newHorizontalBox();
uiBoxAppend(page15, uiControl(hbox), 0);
uiBoxAppend(hbox, uiControl(uiNewLabel("Size")), 0);
width = uiNewSpinbox(INT_MIN, INT_MAX);
uiBoxAppend(hbox, uiControl(width), 1);
height = uiNewSpinbox(INT_MIN, INT_MAX);
uiBoxAppend(hbox, uiControl(height), 1);
// button = uiNewButton("Center");
// uiBoxAppend(hbox, uiControl(button), 0);
uiSpinboxOnChanged(width, sizeWidth, w);
uiSpinboxOnChanged(height, sizeHeight, w);
// uiButtonOnClicked(button, center, w);
uiWindowOnContentSizeChanged(w, onSize, NULL);
updatesize(w);
return page15;
}

View File

@ -5,6 +5,7 @@
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include "../ui.h"
// main.c
@ -85,3 +86,6 @@ extern uiBox *makePage13(void);
// page14.c
extern uiTab *makePage14(void);
// page15.c
extern uiBox *makePage15(uiWindow *);

7
ui.h
View File

@ -99,6 +99,13 @@ typedef struct uiWindow uiWindow;
#define uiWindow(this) ((uiWindow *) (this))
_UI_EXTERN char *uiWindowTitle(uiWindow *w);
_UI_EXTERN void uiWindowSetTitle(uiWindow *w, const char *title);
_UI_EXTERN void uiWindowPosition(uiWindow *w, int *x, int *y);
_UI_EXTERN void uiWindowSetPosition(uiWindow *w, int x, int y);
_UI_EXTERN void uiWindowCenter(uiWindow *w);
_UI_EXTERN void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data);
_UI_EXTERN void uiWindowContentSize(uiWindow *w, int *width, int *height);
_UI_EXTERN void uiWindowSetContentSize(uiWindow *w, int width, int height);
_UI_EXTERN void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data);
_UI_EXTERN void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *w, void *data), void *data);
_UI_EXTERN void uiWindowSetChild(uiWindow *w, uiControl *child);
_UI_EXTERN int uiWindowMargined(uiWindow *w);

View File

@ -12,13 +12,22 @@ struct uiWindow {
GtkContainer *vboxContainer;
GtkBox *vbox;
GtkWidget *childHolderWidget;
GtkContainer *childHolderContainer;
GtkWidget *menubar;
struct child *child;
uiControl *child;
int margined;
int (*onClosing)(uiWindow *, void *);
void *onClosingData;
void (*onPositionChanged)(uiWindow *, void *);
void *onPositionChangedData;
gboolean changingPosition;
void (*onContentSizeChanged)(uiWindow *, void *);
void *onContentSizeChangedData;
gboolean changingSize;
};
static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data)
@ -32,11 +41,39 @@ static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data)
return TRUE;
}
static gboolean onConfigure(GtkWidget *win, GdkEvent *e, gpointer data)
{
uiWindow *w = uiWindow(data);
// there doesn't seem to be a way to determine if only moving or only resizing is happening :/
if (w->changingPosition)
w->changingPosition = FALSE;
else
(*(w->onPositionChanged))(w, w->onPositionChangedData);
// always continue handling
return FALSE;
}
static void onSizeAllocate(GtkWidget *widget, GdkRectangle *allocation, gpointer data)
{
uiWindow *w = uiWindow(data);
if (w->changingSize)
w->changingSize = FALSE;
else
(*(w->onContentSizeChanged))(w, w->onContentSizeChangedData);
}
static int defaultOnClosing(uiWindow *w, void *data)
{
return 0;
}
static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data)
{
// do nothing
}
static void uiWindowDestroy(uiControl *c)
{
uiWindow *w = uiWindow(c);
@ -44,11 +81,15 @@ static void uiWindowDestroy(uiControl *c)
// first hide ourselves
gtk_widget_hide(w->widget);
// now destroy the child
if (w->child != NULL)
childDestroy(w->child);
if (w->child != NULL) {
uiControlSetParent(w->child, NULL);
uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE);
uiControlDestroy(w->child);
}
// now destroy the menus, if any
if (w->menubar != NULL)
freeMenubar(w->menubar);
gtk_widget_destroy(w->childHolderWidget);
gtk_widget_destroy(w->vboxWidget);
// and finally free ourselves
g_object_unref(w->widget);
@ -101,22 +142,99 @@ void uiWindowSetTitle(uiWindow *w, const char *title)
gtk_window_set_title(w->window, title);
}
// TODO allow specifying either as NULL on all platforms
void uiWindowPosition(uiWindow *w, int *x, int *y)
{
gint rx, ry;
gtk_window_get_position(w->window, &rx, &ry);
*x = rx;
*y = ry;
}
void uiWindowSetPosition(uiWindow *w, int x, int y)
{
w->changingPosition = TRUE;
gtk_window_move(w->window, x, y);
// gtk_window_move() is asynchronous
// we need to wait for a configure-event
// thanks to hergertme in irc.gimp.net/#gtk+
while (w->changingPosition)
if (gtk_main_iteration() != FALSE)
break; // stop early if gtk_main_quit() called
}
void uiWindowCenter(uiWindow *w)
{
gint x, y;
GtkAllocation winalloc;
GdkWindow *gdkwin;
GdkScreen *screen;
GdkRectangle workarea;
gtk_widget_get_allocation(w->widget, &winalloc);
gdkwin = gtk_widget_get_window(w->widget);
screen = gdk_window_get_screen(gdkwin);
gdk_screen_get_monitor_workarea(screen,
gdk_screen_get_monitor_at_window(screen, gdkwin),
&workarea);
x = (workarea.width - winalloc.width) / 2;
y = (workarea.height - winalloc.height) / 2;
// TODO move up slightly? see what Mutter or GNOME Shell or GNOME Terminal do(es)?
uiWindowSetPosition(w, x, y);
}
void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onPositionChanged = f;
w->onPositionChangedData = data;
}
void uiWindowContentSize(uiWindow *w, int *width, int *height)
{
GtkAllocation allocation;
gtk_widget_get_allocation(w->childHolderWidget, &allocation);
*width = allocation.width;
*height = allocation.height;
}
// TODO what happens if the size is already the current one?
// TODO a spurious size-allocate gets sent after this function returns
void uiWindowSetContentSize(uiWindow *w, int width, int height)
{
w->changingSize = TRUE;
gtk_widget_set_size_request(w->childHolderWidget, width, height);
while (w->changingSize)
if (gtk_main_iteration() != FALSE)
break; // stop early if gtk_main_quit() called
gtk_widget_set_size_request(w->childHolderWidget, -1, -1);
}
void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onContentSizeChanged = f;
w->onContentSizeChangedData = data;
}
void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
w->onClosing = f;
w->onClosingData = data;
}
// TODO save and restore expands and aligns
void uiWindowSetChild(uiWindow *w, uiControl *child)
{
if (w->child != NULL)
childRemove(w->child);
w->child = newChildWithBox(child, uiControl(w), w->vboxContainer, w->margined);
if (w->child != NULL) {
gtk_widget_set_hexpand(childBox(w->child), TRUE);
gtk_widget_set_halign(childBox(w->child), GTK_ALIGN_FILL);
gtk_widget_set_vexpand(childBox(w->child), TRUE);
gtk_widget_set_valign(childBox(w->child), GTK_ALIGN_FILL);
uiControlSetParent(w->child, NULL);
uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, TRUE);
}
w->child = child;
if (w->child != NULL) {
uiControlSetParent(w->child, uiControl(w));
uiUnixControlSetContainer(uiUnixControl(w->child), w->childHolderContainer, FALSE);
}
}
@ -128,8 +246,7 @@ int uiWindowMargined(uiWindow *w)
void uiWindowSetMargined(uiWindow *w, int margined)
{
w->margined = margined;
if (w->child != NULL)
childSetMargined(w->child, w->margined);
setMargined(w->childHolderContainer, w->margined);
}
uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
@ -157,12 +274,24 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
gtk_container_add(w->vboxContainer, w->menubar);
}
w->childHolderWidget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
w->childHolderContainer = GTK_CONTAINER(w->childHolderWidget);
gtk_widget_set_hexpand(w->childHolderWidget, TRUE);
gtk_widget_set_halign(w->childHolderWidget, GTK_ALIGN_FILL);
gtk_widget_set_vexpand(w->childHolderWidget, TRUE);
gtk_widget_set_valign(w->childHolderWidget, GTK_ALIGN_FILL);
gtk_container_add(w->vboxContainer, w->childHolderWidget);
// show everything in the vbox, but not the GtkWindow itself
gtk_widget_show_all(w->vboxWidget);
// and connect our OnClosing() event
// and connect our events
g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w);
g_signal_connect(w->widget, "configure-event", G_CALLBACK(onConfigure), w);
g_signal_connect(w->childHolderWidget, "size-allocate", G_CALLBACK(onSizeAllocate), w);
uiWindowOnClosing(w, defaultOnClosing, NULL);
uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL);
uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL);
// normally it's SetParent() that does this, but we can't call SetParent() on a uiWindow
// TODO we really need to clean this up

View File

@ -14,6 +14,12 @@ struct uiWindow {
void *onClosingData;
int margined;
BOOL hasMenubar;
void (*onPositionChanged)(uiWindow *, void *);
void *onPositionChangedData;
BOOL changingPosition; // to avoid triggering the above when programmatically doing this
void (*onContentSizeChanged)(uiWindow *, void *);
void *onContentSizeChangedData;
BOOL changingSize;
};
// from https://msdn.microsoft.com/en-us/library/windows/desktop/dn742486.aspx#sizingandspacing
@ -35,7 +41,6 @@ static void windowMargins(uiWindow *w, int *mx, int *my)
static void windowRelayout(uiWindow *w)
{
uiWindowsSizing sizing;
int x, y, width, height;
RECT r;
int mx, my;
@ -87,8 +92,15 @@ static LRESULT CALLBACK windowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARA
runMenuEvent(LOWORD(wParam), uiWindow(w));
return 0;
case WM_WINDOWPOSCHANGED:
if ((wp->flags & SWP_NOMOVE) == 0)
if (!w->changingPosition)
(*(w->onPositionChanged))(w, w->onPositionChangedData);
// and continue anyway
if ((wp->flags & SWP_NOSIZE) != 0)
break;
if (w->onContentSizeChanged != NULL) // TODO figure out why this is happening too early
if (!w->changingSize)
(*(w->onContentSizeChanged))(w, w->onContentSizeChangedData);
windowRelayout(w);
return 0;
case WM_GETMINMAXINFO:
@ -138,6 +150,11 @@ static int defaultOnClosing(uiWindow *w, void *data)
return 0;
}
static void defaultOnPositionContentSizeChanged(uiWindow *w, void *data)
{
// do nothing
}
static std::map<uiWindow *, bool> windows;
static void uiWindowDestroy(uiControl *c)
@ -224,7 +241,6 @@ uiWindowsControlDefaultSetParentHWND(uiWindow)
static void uiWindowMinimumSize(uiWindowsControl *c, int *width, int *height)
{
uiWindow *w = uiWindow(c);
uiWindowsSizing sizing;
int mx, my;
*width = 0;
@ -277,6 +293,100 @@ void uiWindowSetTitle(uiWindow *w, const char *title)
// don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long)
}
void uiWindowPosition(uiWindow *w, int *x, int *y)
{
RECT r;
uiWindowsEnsureGetWindowRect(w->hwnd, &r);
*x = r.left;
*y = r.top;
}
void uiWindowSetPosition(uiWindow *w, int x, int y)
{
w->changingPosition = TRUE;
if (SetWindowPos(w->hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER) == 0)
logLastError(L"error moving window");
w->changingPosition = FALSE;
}
// this is used for both fullscreening and centering
// see also https://blogs.msdn.microsoft.com/oldnewthing/20100412-00/?p=14353 and https://blogs.msdn.microsoft.com/oldnewthing/20050505-04/?p=35703
static void windowMonitorRect(HWND hwnd, RECT *r)
{
HMONITOR monitor;
MONITORINFO mi;
monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
ZeroMemory(&mi, sizeof (MONITORINFO));
mi.cbSize = sizeof (MONITORINFO);
if (GetMonitorInfoW(monitor, &mi) == 0) {
logLastError(L"error getting window monitor rect");
// default to SM_CXSCREEN x SM_CYSCREEN to be safe
r->left = 0;
r->top = 0;
r->right = GetSystemMetrics(SM_CXSCREEN);
r->bottom = GetSystemMetrics(SM_CYSCREEN);
return;
}
*r = mi.rcMonitor;
}
// TODO use the work rect instead?
void uiWindowCenter(uiWindow *w)
{
RECT wr, mr;
int x, y;
LONG wwid, mwid;
LONG wht, mht;
uiWindowsEnsureGetWindowRect(w->hwnd, &wr);
windowMonitorRect(w->hwnd, &mr);
wwid = wr.right - wr.left;
mwid = mr.right - mr.left;
x = (mwid - wwid) / 2;
wht = wr.bottom - wr.top;
mht = mr.bottom - mr.top;
y = (mht - wht) / 2;
// y is now evenly divided, however https://msdn.microsoft.com/en-us/library/windows/desktop/dn742502(v=vs.85).aspx says that 45% should go above and 55% should go below
// so just move 5% of the way up
// TODO should this be on the work area?
// TODO is this calculation correct?
y -= y / 20;
uiWindowSetPosition(w, x, y);
}
void uiWindowContentSize(uiWindow *w, int *width, int *height)
{
RECT r;
uiWindowsEnsureGetClientRect(w->hwnd, &r);
*width = r.right - r.left;
*height = r.bottom - r.top;
}
// TODO should this disallow too small?
void uiWindowSetContentSize(uiWindow *w, int width, int height)
{
w->changingSize = TRUE;
clientSizeToWindowSize(w->hwnd, &width, &height, w->hasMenubar);
if (SetWindowPos(w->hwnd, NULL, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0)
logLastError(L"error resizing window");
w->changingSize = FALSE;
}
void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onContentSizeChanged = f;
w->onContentSizeChangedData = data;
}
void uiWindowOnPositionChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data)
{
w->onPositionChanged = f;
w->onPositionChangedData = data;
}
void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
w->onClosing = f;
@ -373,6 +483,8 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
setClientSize(w, width, height, hasMenubarBOOL, style, exstyle);
uiWindowOnClosing(w, defaultOnClosing, NULL);
uiWindowOnPositionChanged(w, defaultOnPositionContentSizeChanged, NULL);
uiWindowOnContentSizeChanged(w, defaultOnPositionContentSizeChanged, NULL);
windows[w] = true;
return w;