diff options
Diffstat (limited to 'win/tkWinWindow.c')
-rw-r--r-- | win/tkWinWindow.c | 796 |
1 files changed, 796 insertions, 0 deletions
diff --git a/win/tkWinWindow.c b/win/tkWinWindow.c new file mode 100644 index 0000000..2b8eb41 --- /dev/null +++ b/win/tkWinWindow.c @@ -0,0 +1,796 @@ +/* + * tkWinWindow.c -- + * + * Xlib emulation routines for Windows related to creating, + * displaying and destroying windows. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * SCCS: @(#) tkWinWindow.c 1.23 97/07/01 18:14:13 + */ + +#include "tkWinInt.h" + +/* + * The windowTable maps from HWND to Tk_Window handles. + */ + +static Tcl_HashTable windowTable; + +/* + * Have statics in this module been initialized? + */ + +static int initialized = 0; + +/* + * Forward declarations for procedures defined in this file: + */ + +static void NotifyVisibility _ANSI_ARGS_((XEvent *eventPtr, + TkWindow *winPtr)); +static void StackWindow _ANSI_ARGS_((Window w, Window sibling, + int stack_mode)); + +/* + *---------------------------------------------------------------------- + * + * Tk_AttachHWND -- + * + * This function binds an HWND and a reflection procedure to + * the specified Tk_Window. + * + * Results: + * Returns an X Window that encapsulates the HWND. + * + * Side effects: + * May allocate a new X Window. Also enters the HWND into the + * global window table. + * + *---------------------------------------------------------------------- + */ + +Window +Tk_AttachHWND(tkwin, hwnd) + Tk_Window tkwin; + HWND hwnd; +{ + int new; + Tcl_HashEntry *entryPtr; + TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin); + + if (!initialized) { + Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS); + initialized = 1; + } + + /* + * Allocate a new drawable if necessary. Otherwise, remove the + * previous HWND from from the window table. + */ + + if (twdPtr == NULL) { + twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable)); + twdPtr->type = TWD_WINDOW; + twdPtr->window.winPtr = (TkWindow *) tkwin; + } else if (twdPtr->window.handle != NULL) { + entryPtr = Tcl_FindHashEntry(&windowTable, + (char *)twdPtr->window.handle); + Tcl_DeleteHashEntry(entryPtr); + } + + /* + * Insert the new HWND into the window table. + */ + + twdPtr->window.handle = hwnd; + entryPtr = Tcl_CreateHashEntry(&windowTable, (char *)hwnd, &new); + Tcl_SetHashValue(entryPtr, (ClientData)tkwin); + + return (Window)twdPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_HWNDToWindow -- + * + * This function retrieves a Tk_Window from the window table + * given an HWND. + * + * Results: + * Returns the matching Tk_Window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tk_Window +Tk_HWNDToWindow(hwnd) + HWND hwnd; +{ + Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&windowTable, (char*)hwnd); + if (entryPtr != NULL) { + return (Tk_Window) Tcl_GetHashValue(entryPtr); + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetHWND -- + * + * This function extracts the HWND from an X Window. + * + * Results: + * Returns the HWND associated with the Window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +HWND +Tk_GetHWND(window) + Window window; +{ + TkWinDrawable *twdPtr = (TkWinDrawable *) window; + return twdPtr->window.handle; +} + +/* + *---------------------------------------------------------------------- + * + * TkpPrintWindowId -- + * + * This routine stores the string representation of the + * platform dependent window handle for an X Window in the + * given buffer. + * + * Results: + * Returns the result in the specified buffer. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpPrintWindowId(buf, window) + char *buf; /* Pointer to string large enough to hold + * the hex representation of a pointer. */ + Window window; /* Window to be printed into buffer. */ +{ + HWND hwnd = (window) ? Tk_GetHWND(window) : 0; + sprintf(buf, "0x%x", (unsigned int) hwnd); +} + +/* + *---------------------------------------------------------------------- + * + * TkpScanWindowId -- + * + * Given a string which represents the platform dependent window + * handle, produce the X Window id for the window. + * + * Results: + * The return value is normally TCL_OK; in this case *idPtr + * will be set to the X Window id equivalent to string. If + * string is improperly formed then TCL_ERROR is returned and + * an error message will be left in interp->result. If the + * number does not correspond to a Tk Window, then *idPtr will + * be set to None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpScanWindowId(interp, string, idPtr) + Tcl_Interp *interp; /* Interpreter to use for error reporting. */ + char *string; /* String containing a (possibly signed) + * integer in a form acceptable to strtol. */ + int *idPtr; /* Place to store converted result. */ +{ + int number; + Tk_Window tkwin; + + if (Tcl_GetInt(interp, string, &number) != TCL_OK) { + return TCL_ERROR; + } + tkwin = Tk_HWNDToWindow((HWND)number); + if (tkwin) { + *idPtr = Tk_WindowId(tkwin); + } else { + *idPtr = None; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeWindow -- + * + * Creates a Windows window object based on the current attributes + * of the specified TkWindow. + * + * Results: + * Returns a pointer to a new TkWinDrawable cast to a Window. + * + * Side effects: + * Creates a new window. + * + *---------------------------------------------------------------------- + */ + +Window +TkpMakeWindow(winPtr, parent) + TkWindow *winPtr; + Window parent; +{ + HWND parentWin; + int style; + HWND hwnd; + + if (parent != None) { + parentWin = Tk_GetHWND(parent); + style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + } else { + parentWin = NULL; + style = WS_POPUP | WS_CLIPCHILDREN; + } + + /* + * Create the window, then ensure that it is at the top of the + * stacking order. + */ + + hwnd = CreateWindow(TK_WIN_CHILD_CLASS_NAME, NULL, style, + Tk_X(winPtr), Tk_Y(winPtr), Tk_Width(winPtr), Tk_Height(winPtr), + parentWin, NULL, Tk_GetHINSTANCE(), NULL); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + return Tk_AttachHWND((Tk_Window)winPtr, hwnd); +} + +/* + *---------------------------------------------------------------------- + * + * XDestroyWindow -- + * + * Destroys the given window. + * + * Results: + * None. + * + * Side effects: + * Sends the WM_DESTROY message to the window and then destroys + * it the Win32 resources associated with the window. + * + *---------------------------------------------------------------------- + */ + +void +XDestroyWindow(display, w) + Display* display; + Window w; +{ + Tcl_HashEntry *entryPtr; + TkWinDrawable *twdPtr = (TkWinDrawable *)w; + TkWindow *winPtr = TkWinGetWinPtr(w); + HWND hwnd = Tk_GetHWND(w); + + display->request++; + + /* + * Remove references to the window in the pointer module then + * release the drawable. + */ + + TkPointerDeadWindow(winPtr); + + entryPtr = Tcl_FindHashEntry(&windowTable, (char*)hwnd); + if (entryPtr != NULL) { + Tcl_DeleteHashEntry(entryPtr); + } + + ckfree((char *)twdPtr); + + /* + * Don't bother destroying the window if we are going to destroy + * the parent later. + */ + + if (hwnd != NULL && !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) { + DestroyWindow(hwnd); + } +} + +/* + *---------------------------------------------------------------------- + * + * XMapWindow -- + * + * Cause the given window to become visible. + * + * Results: + * None + * + * Side effects: + * Causes the window state to change, and generates a MapNotify + * event. + * + *---------------------------------------------------------------------- + */ + +void +XMapWindow(display, w) + Display* display; + Window w; +{ + XEvent event; + TkWindow *parentPtr; + TkWindow *winPtr = TkWinGetWinPtr(w); + + display->request++; + + ShowWindow(TkWinGetHWND(w), SW_SHOWNORMAL); + winPtr->flags |= TK_MAPPED; + + /* + * Check to see if this window is visible now. If all of the parent + * windows up to the first toplevel are mapped, then this window and + * its mapped children have just become visible. + */ + + if (!(winPtr->flags & TK_TOP_LEVEL)) { + for (parentPtr = winPtr->parentPtr; ; + parentPtr = parentPtr->parentPtr) { + if ((parentPtr == NULL) || !(parentPtr->flags & TK_MAPPED)) { + return; + } + if (parentPtr->flags & TK_TOP_LEVEL) { + break; + } + } + } else { + event.type = MapNotify; + event.xmap.serial = display->request; + event.xmap.send_event = False; + event.xmap.display = display; + event.xmap.event = winPtr->window; + event.xmap.window = winPtr->window; + event.xmap.override_redirect = winPtr->atts.override_redirect; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + } + + /* + * Generate VisibilityNotify events for this window and its mapped + * children. + */ + + event.type = VisibilityNotify; + event.xvisibility.serial = display->request; + event.xvisibility.send_event = False; + event.xvisibility.display = display; + event.xvisibility.window = winPtr->window; + event.xvisibility.state = VisibilityUnobscured; + NotifyVisibility(&event, winPtr); +} + +/* + *---------------------------------------------------------------------- + * + * NotifyVisibility -- + * + * This function recursively notifies the mapped children of the + * specified window of a change in visibility. Note that we don't + * properly report the visibility state, since Windows does not + * provide that info. The eventPtr argument must point to an event + * that has been completely initialized except for the window slot. + * + * Results: + * None. + * + * Side effects: + * Generates lots of events. + * + *---------------------------------------------------------------------- + */ + +static void +NotifyVisibility(eventPtr, winPtr) + XEvent *eventPtr; /* Initialized VisibilityNotify event. */ + TkWindow *winPtr; /* Window to notify. */ +{ + if (winPtr->atts.event_mask & VisibilityChangeMask) { + eventPtr->xvisibility.window = winPtr->window; + Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL); + } + for (winPtr = winPtr->childList; winPtr != NULL; + winPtr = winPtr->nextPtr) { + if (winPtr->flags & TK_MAPPED) { + NotifyVisibility(eventPtr, winPtr); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * XUnmapWindow -- + * + * Cause the given window to become invisible. + * + * Results: + * None + * + * Side effects: + * Causes the window state to change, and generates an UnmapNotify + * event. + * + *---------------------------------------------------------------------- + */ + +void +XUnmapWindow(display, w) + Display* display; + Window w; +{ + XEvent event; + TkWindow *winPtr = TkWinGetWinPtr(w); + + display->request++; + + /* + * Bug fix: Don't short circuit this routine based on TK_MAPPED because + * it will be cleared before XUnmapWindow is called. + */ + + ShowWindow(TkWinGetHWND(w), SW_HIDE); + winPtr->flags &= ~TK_MAPPED; + + if (winPtr->flags & TK_TOP_LEVEL) { + event.type = UnmapNotify; + event.xunmap.serial = display->request; + event.xunmap.send_event = False; + event.xunmap.display = display; + event.xunmap.event = winPtr->window; + event.xunmap.window = winPtr->window; + event.xunmap.from_configure = False; + Tk_HandleEvent(&event); + } +} + +/* + *---------------------------------------------------------------------- + * + * XMoveResizeWindow -- + * + * Move and resize a window relative to its parent. + * + * Results: + * None. + * + * Side effects: + * Repositions and resizes the specified window. + * + *---------------------------------------------------------------------- + */ + +void +XMoveResizeWindow(display, w, x, y, width, height) + Display* display; + Window w; + int x; /* Position relative to parent. */ + int y; + unsigned int width; + unsigned int height; +{ + display->request++; + MoveWindow(TkWinGetHWND(w), x, y, width, height, TRUE); +} + +/* + *---------------------------------------------------------------------- + * + * XMoveWindow -- + * + * Move a window relative to its parent. + * + * Results: + * None. + * + * Side effects: + * Repositions the specified window. + * + *---------------------------------------------------------------------- + */ + +void +XMoveWindow(display, w, x, y) + Display* display; + Window w; + int x; + int y; +{ + TkWindow *winPtr = TkWinGetWinPtr(w); + + display->request++; + + MoveWindow(TkWinGetHWND(w), x, y, winPtr->changes.width, + winPtr->changes.height, TRUE); +} + +/* + *---------------------------------------------------------------------- + * + * XResizeWindow -- + * + * Resize a window. + * + * Results: + * None. + * + * Side effects: + * Resizes the specified window. + * + *---------------------------------------------------------------------- + */ + +void +XResizeWindow(display, w, width, height) + Display* display; + Window w; + unsigned int width; + unsigned int height; +{ + TkWindow *winPtr = TkWinGetWinPtr(w); + + display->request++; + + MoveWindow(TkWinGetHWND(w), winPtr->changes.x, winPtr->changes.y, width, + height, TRUE); +} + +/* + *---------------------------------------------------------------------- + * + * XRaiseWindow -- + * + * Change the stacking order of a window. + * + * Results: + * None. + * + * Side effects: + * Changes the stacking order of the specified window. + * + *---------------------------------------------------------------------- + */ + +void +XRaiseWindow(display, w) + Display* display; + Window w; +{ + HWND window = TkWinGetHWND(w); + + display->request++; + SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); +} + +/* + *---------------------------------------------------------------------- + * + * XConfigureWindow -- + * + * Change the size, position, stacking, or border of the specified + * window. + * + * Results: + * None. + * + * Side effects: + * Changes the attributes of the specified window. Note that we + * ignore the passed in values and use the values stored in the + * TkWindow data structure. + * + *---------------------------------------------------------------------- + */ + +void +XConfigureWindow(display, w, value_mask, values) + Display* display; + Window w; + unsigned int value_mask; + XWindowChanges* values; +{ + TkWindow *winPtr = TkWinGetWinPtr(w); + HWND hwnd = TkWinGetHWND(w); + + display->request++; + + /* + * Change the shape and/or position of the window. + */ + + if (value_mask & (CWX|CWY|CWWidth|CWHeight)) { + MoveWindow(hwnd, winPtr->changes.x, winPtr->changes.y, + winPtr->changes.width, winPtr->changes.height, TRUE); + } + + /* + * Change the stacking order of the window. + */ + + if (value_mask & CWStackMode) { + HWND sibling; + if ((value_mask & CWSibling) && (values->sibling != None)) { + sibling = Tk_GetHWND(values->sibling); + } else { + sibling = NULL; + } + TkWinSetWindowPos(hwnd, sibling, values->stack_mode); + } +} + +/* + *---------------------------------------------------------------------- + * + * XClearWindow -- + * + * Clears the entire window to the current background color. + * + * Results: + * None. + * + * Side effects: + * Erases the current contents of the window. + * + *---------------------------------------------------------------------- + */ + +void +XClearWindow(display, w) + Display* display; + Window w; +{ + RECT rc; + HBRUSH brush; + HPALETTE oldPalette, palette; + TkWindow *winPtr; + HWND hwnd = TkWinGetHWND(w); + HDC dc = GetDC(hwnd); + + palette = TkWinGetPalette(display->screens[0].cmap); + oldPalette = SelectPalette(dc, palette, FALSE); + + display->request++; + + winPtr = TkWinGetWinPtr(w); + brush = CreateSolidBrush(winPtr->atts.background_pixel); + GetWindowRect(hwnd, &rc); + rc.right = rc.right - rc.left; + rc.bottom = rc.bottom - rc.top; + rc.left = rc.top = 0; + FillRect(dc, &rc, brush); + + DeleteObject(brush); + SelectPalette(dc, oldPalette, TRUE); + ReleaseDC(hwnd, dc); +} + +/* + *---------------------------------------------------------------------- + * + * XChangeWindowAttributes -- + * + * This function is called when the attributes on a window are + * updated. Since Tk maintains all of the window state, the only + * relevant value is the cursor. + * + * Results: + * None. + * + * Side effects: + * May cause the mouse position to be updated. + * + *---------------------------------------------------------------------- + */ + +void +XChangeWindowAttributes(display, w, valueMask, attributes) + Display* display; + Window w; + unsigned long valueMask; + XSetWindowAttributes* attributes; +{ + if (valueMask & CWCursor) { + XDefineCursor(display, w, attributes->cursor); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWinSetWindowPos -- + * + * Adjust the stacking order of a window relative to a second + * window (or NULL). + * + * Results: + * None. + * + * Side effects: + * Moves the specified window in the stacking order. + * + *---------------------------------------------------------------------- + */ + +void +TkWinSetWindowPos(hwnd, siblingHwnd, pos) + HWND hwnd; /* Window to restack. */ + HWND siblingHwnd; /* Sibling window. */ + int pos; /* One of Above or Below. */ +{ + HWND temp; + + /* + * Since Windows does not support Above mode, we place the + * specified window below the sibling and then swap them. + */ + + if (siblingHwnd) { + if (pos == Above) { + SetWindowPos(hwnd, siblingHwnd, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + temp = hwnd; + hwnd = siblingHwnd; + siblingHwnd = temp; + } + } else { + siblingHwnd = (pos == Above) ? HWND_TOP : HWND_BOTTOM; + } + + SetWindowPos(hwnd, siblingHwnd, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); +} + +/* + *---------------------------------------------------------------------- + * + * TkpWindowWasRecentlyDeleted -- + * + * Determines whether we know if the window given as argument was + * recently deleted. Called by the generic code error handler to + * handle BadWindow events. + * + * Results: + * Always 0. We do not keep this information on Windows. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpWindowWasRecentlyDeleted(win, dispPtr) + Window win; + TkDisplay *dispPtr; +{ + return 0; +} |