windowmaker-wl/WINGs/wwindow.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);
}