458 lines
11 KiB
C
458 lines
11 KiB
C
|
|
#include "wconfig.h"
|
|
|
|
#include "wwindow_p.h"
|
|
|
|
#include "../src/GNUstep.h"
|
|
|
|
|
|
static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned *, unsigned *);
|
|
|
|
struct W_ViewDelegate _WindowViewDelegate = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
willResizeWindow
|
|
};
|
|
|
|
#define DEFAULT_WIDTH 400
|
|
#define DEFAULT_HEIGHT 180
|
|
|
|
static void destroyWindow(_Window * win);
|
|
|
|
static void handleEvents(WMEvent * event, void *clientData);
|
|
|
|
static void realizeWindow(WMWindow * win);
|
|
|
|
static void realizeObserver(void *self, WMNotification * not)
|
|
{
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) not;
|
|
|
|
realizeWindow(self);
|
|
}
|
|
|
|
WMWindow *WMCreatePanelWithStyleForWindow(WMWindow * owner, const char *name, int style)
|
|
{
|
|
WMWindow *win;
|
|
|
|
win = WMCreateWindowWithStyle(owner->view->screen, name, style);
|
|
win->owner = owner;
|
|
|
|
return win;
|
|
}
|
|
|
|
WMWindow *WMCreatePanelForWindow(WMWindow * owner, const char *name)
|
|
{
|
|
return WMCreatePanelWithStyleForWindow(owner, name,
|
|
WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
|
|
}
|
|
|
|
void WMChangePanelOwner(WMWindow * win, WMWindow * newOwner)
|
|
{
|
|
win->owner = newOwner;
|
|
|
|
if (win->view->flags.realized && newOwner) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_realize)
|
|
vb->window_realize(scr->viewBackendCtx, win->view,
|
|
win->wname, WMGetApplicationName(),
|
|
newOwner->view);
|
|
}
|
|
}
|
|
|
|
WMWindow *WMCreateWindow(WMScreen * screen, const char *name)
|
|
{
|
|
return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
|
|
| WMClosableWindowMask
|
|
| WMMiniaturizableWindowMask | WMResizableWindowMask);
|
|
}
|
|
|
|
WMWindow *WMCreateWindowWithStyle(WMScreen * screen, const char *name, int style)
|
|
{
|
|
_Window *win;
|
|
|
|
win = wmalloc(sizeof(_Window));
|
|
win->widgetClass = WC_Window;
|
|
|
|
win->view = W_CreateTopView(screen);
|
|
if (!win->view) {
|
|
wfree(win);
|
|
return NULL;
|
|
}
|
|
win->view->self = win;
|
|
|
|
win->view->delegate = &_WindowViewDelegate;
|
|
|
|
win->wname = wstrdup(name);
|
|
|
|
/* add to the window list of the screen (application) */
|
|
win->nextPtr = screen->windowList;
|
|
screen->windowList = win;
|
|
|
|
WMCreateEventHandler(win->view, WM_EVMASK_EXPOSURE | WM_EVMASK_STRUCTURE_NOTIFY
|
|
| ClientMessageMask | WM_EVMASK_FOCUS_CHANGE, handleEvents, win);
|
|
|
|
W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
|
|
|
WMAddNotificationObserver(realizeObserver, win, WMViewRealizedNotification, win->view);
|
|
|
|
win->flags.style = style;
|
|
|
|
win->level = WMNormalWindowLevel;
|
|
|
|
/* kluge. Find a better solution */
|
|
W_SetFocusOfTopLevel(win->view, win->view);
|
|
|
|
return win;
|
|
}
|
|
|
|
void WMSetWindowTitle(WMWindow * win, const char *title)
|
|
{
|
|
wassertr(title != NULL);
|
|
|
|
if (win->title != NULL)
|
|
wfree(win->title);
|
|
|
|
win->title = wstrdup(title);
|
|
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_title)
|
|
vb->window_set_title(scr->viewBackendCtx, win->view, title);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowCloseAction(WMWindow * win, WMAction * action, void *clientData)
|
|
{
|
|
win->closeAction = action;
|
|
win->closeData = clientData;
|
|
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_realize)
|
|
vb->window_realize(scr->viewBackendCtx, win->view,
|
|
win->wname, WMGetApplicationName(),
|
|
win->owner ? win->owner->view : NULL);
|
|
}
|
|
}
|
|
|
|
static void willResizeWindow(W_ViewDelegate * self, WMView * view, unsigned *width, unsigned *height)
|
|
{
|
|
WMWindow *win = (WMWindow *) view->self;
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) self;
|
|
|
|
if (win->minSize.width > 0 && win->minSize.height > 0) {
|
|
if (*width < win->minSize.width)
|
|
*width = win->minSize.width;
|
|
if (*height < win->minSize.height)
|
|
*height = win->minSize.height;
|
|
}
|
|
|
|
if (win->maxSize.width > 0 && win->maxSize.height > 0) {
|
|
if (*width > win->maxSize.width)
|
|
*width = win->maxSize.width;
|
|
if (*height > win->maxSize.height)
|
|
*height = win->maxSize.height;
|
|
}
|
|
}
|
|
|
|
static void realizeWindow(WMWindow * win)
|
|
{
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
|
|
if (vb->window_realize)
|
|
vb->window_realize(scr->viewBackendCtx, win->view,
|
|
win->wname, WMGetApplicationName(),
|
|
win->owner ? win->owner->view : NULL);
|
|
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
|
|
void WMSetWindowAspectRatio(WMWindow * win, int minX, int minY, int maxX, int maxY)
|
|
{
|
|
win->flags.setAspect = 1;
|
|
win->minAspect.x = minX;
|
|
win->minAspect.y = minY;
|
|
win->maxAspect.x = maxX;
|
|
win->maxAspect.y = maxY;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowInitialPosition(WMWindow * win, int x, int y)
|
|
{
|
|
win->flags.setPPos = 1;
|
|
win->ppos.x = x;
|
|
win->ppos.y = y;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
WMMoveWidget(win, x, y);
|
|
}
|
|
|
|
void WMSetWindowUserPosition(WMWindow * win, int x, int y)
|
|
{
|
|
win->flags.setUPos = 1;
|
|
win->upos.x = x;
|
|
win->upos.y = y;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
WMMoveWidget(win, x, y);
|
|
}
|
|
|
|
void WMSetWindowMinSize(WMWindow * win, unsigned width, unsigned height)
|
|
{
|
|
win->minSize.width = width;
|
|
win->minSize.height = height;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowMaxSize(WMWindow * win, unsigned width, unsigned height)
|
|
{
|
|
win->maxSize.width = width;
|
|
win->maxSize.height = height;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowBaseSize(WMWindow * win, unsigned width, unsigned height)
|
|
{
|
|
/* TODO: validate sizes */
|
|
win->baseSize.width = width;
|
|
win->baseSize.height = height;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowResizeIncrements(WMWindow * win, unsigned wIncr, unsigned hIncr)
|
|
{
|
|
win->resizeIncrement.width = wIncr;
|
|
win->resizeIncrement.height = hIncr;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_geometry)
|
|
vb->window_set_geometry(scr->viewBackendCtx, win->view);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowLevel(WMWindow * win, int level)
|
|
{
|
|
win->level = level;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_realize)
|
|
vb->window_realize(scr->viewBackendCtx, win->view,
|
|
win->wname, WMGetApplicationName(),
|
|
win->owner ? win->owner->view : NULL);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowDocumentEdited(WMWindow * win, Bool flag)
|
|
{
|
|
flag = ((flag == 0) ? 0 : 1);
|
|
if (win->flags.documentEdited != flag) {
|
|
win->flags.documentEdited = flag;
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_realize)
|
|
vb->window_realize(scr->viewBackendCtx, win->view,
|
|
win->wname, WMGetApplicationName(),
|
|
win->owner ? win->owner->view : NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMSetWindowMiniwindowImage(WMWindow * win, RImage * image)
|
|
{
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_icon_image)
|
|
vb->window_set_icon_image(scr->viewBackendCtx, win->view, image);
|
|
}
|
|
}
|
|
|
|
void WMSetWindowMiniwindowPixmap(WMWindow * win, WMPixmap * pixmap)
|
|
{
|
|
if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
|
|
if (win->miniImage)
|
|
WMReleasePixmap(win->miniImage);
|
|
|
|
if (pixmap)
|
|
win->miniImage = WMRetainPixmap(pixmap);
|
|
else
|
|
win->miniImage = NULL;
|
|
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_realize)
|
|
vb->window_realize(scr->viewBackendCtx, win->view,
|
|
win->wname, WMGetApplicationName(),
|
|
win->owner ? win->owner->view : NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMSetWindowMiniwindowTitle(WMWindow * win, const char *title)
|
|
{
|
|
if (win && ((win->miniTitle && !title) || (!win->miniTitle && title)
|
|
|| (title && win->miniTitle && strcoll(title, win->miniTitle) != 0))) {
|
|
if (win->miniTitle)
|
|
wfree(win->miniTitle);
|
|
|
|
if (title)
|
|
win->miniTitle = wstrdup(title);
|
|
else
|
|
win->miniTitle = NULL;
|
|
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_set_icon_title)
|
|
vb->window_set_icon_title(scr->viewBackendCtx, win->view, title);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMCloseWindow(WMWindow * win)
|
|
{
|
|
WMUnmapWidget(win);
|
|
/* withdraw the window */
|
|
if (win->view->flags.realized) {
|
|
W_Screen *scr = win->view->screen;
|
|
const W_ViewBackend *vb = scr->viewBackend;
|
|
if (vb->window_withdraw)
|
|
vb->window_withdraw(scr->viewBackendCtx, win->view);
|
|
}
|
|
}
|
|
|
|
static void handleEvents(WMEvent * event, void *clientData)
|
|
{
|
|
_Window *win = (_Window *) clientData;
|
|
W_View *view = win->view;
|
|
|
|
switch (event->type) {
|
|
case WME_CLIENT_MESSAGE:
|
|
if (event->u.clientMessage.message_type == win->view->screen->protocolsAtom
|
|
&& event->u.clientMessage.format == 32
|
|
&& event->u.clientMessage.data.l[0] == win->view->screen->deleteWindowAtom) {
|
|
|
|
if (win->closeAction) {
|
|
(*win->closeAction) (win, win->closeData);
|
|
}
|
|
}
|
|
break;
|
|
/*
|
|
* was causing windows to ignore commands like closeWindow
|
|
* after the windows is iconized/restored or a workspace change
|
|
* if this is really needed, put the MapNotify portion too and
|
|
* fix the restack bug in wmaker
|
|
case WME_UNMAP:
|
|
WMUnmapWidget(win);
|
|
break;
|
|
*
|
|
case WME_MAP:
|
|
WMMapWidget(win);
|
|
break;
|
|
|
|
*/
|
|
case WME_DESTROY:
|
|
destroyWindow(win);
|
|
break;
|
|
|
|
case WME_CONFIGURE:
|
|
if (event->u.configure.width != view->size.width || event->u.configure.height != view->size.height) {
|
|
|
|
view->size.width = event->u.configure.width;
|
|
view->size.height = event->u.configure.height;
|
|
|
|
if (view->flags.notifySizeChanged) {
|
|
WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
|
|
}
|
|
}
|
|
if (event->u.configure.x != view->pos.x || event->u.configure.y != view->pos.y) {
|
|
view->pos.x = event->u.configure.x;
|
|
view->pos.y = event->u.configure.y;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void destroyWindow(_Window * win)
|
|
{
|
|
WMScreen *scr = win->view->screen;
|
|
|
|
WMRemoveNotificationObserver(win);
|
|
|
|
if (scr->windowList == win) {
|
|
scr->windowList = scr->windowList->nextPtr;
|
|
} else {
|
|
WMWindow *ptr;
|
|
ptr = scr->windowList;
|
|
|
|
if (ptr) {
|
|
while (ptr->nextPtr) {
|
|
if (ptr->nextPtr == win) {
|
|
ptr->nextPtr = ptr->nextPtr->nextPtr;
|
|
break;
|
|
}
|
|
ptr = ptr->nextPtr;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (win->title) {
|
|
wfree(win->title);
|
|
}
|
|
|
|
if (win->miniTitle) {
|
|
wfree(win->miniTitle);
|
|
}
|
|
|
|
if (win->miniImage) {
|
|
WMReleasePixmap(win->miniImage);
|
|
}
|
|
|
|
if (win->wname)
|
|
wfree(win->wname);
|
|
|
|
wfree(win);
|
|
}
|