summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-08-04 19:46:49 -0400
committerPietro Gagliardi <[email protected]>2014-08-04 19:46:49 -0400
commit9ed4ec52597e03b080331efeac526322b669e565 (patch)
tree3fbd62fc272409d26ec10b56a7d546dbb9e5bc98
parent88c01bf69532243f432e03121b922a94d19b0ae1 (diff)
Split layout and Window on Windows to use two separate window classes. This is the first half of the two-part migration of the Windows backend to use container.
-rw-r--r--redo/container_windows.c84
-rw-r--r--redo/layout_windows.go33
-rw-r--r--redo/uitask_windows.go3
-rw-r--r--redo/winapi_windows.h6
-rw-r--r--redo/window_windows.c17
-rw-r--r--redo/window_windows.go38
6 files changed, 148 insertions, 33 deletions
diff --git a/redo/container_windows.c b/redo/container_windows.c
new file mode 100644
index 0000000..5db4548
--- /dev/null
+++ b/redo/container_windows.c
@@ -0,0 +1,84 @@
+/* 17 july 2014 */
+
+#include "winapi_windows.h"
+#include "_cgo_export.h"
+
+/*
+This could all just be part of Window, but doing so just makes things complex.
+In this case, I chose to waste a window handle rather than keep things super complex.
+If this is seriously an issue in the future, I can roll it back.
+*/
+
+#define containerclass L"gouicontainer"
+
+static LRESULT CALLBACK containerWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ void *data;
+ RECT r;
+
+ data = (void *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+ if (data == NULL) {
+ /* the lpParam is available during WM_NCCREATE and WM_CREATE */
+ if (uMsg == WM_NCCREATE) {
+ storelpParam(hwnd, lParam);
+ data = (void *) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+ storeContainerHWND(data, hwnd);
+ }
+ /* act as if we're not ready yet, even during WM_NCCREATE (nothing important to the switch statement below happens here anyway) */
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+
+ switch (uMsg) {
+ case WM_COMMAND:
+ return forwardCommand(hwnd, uMsg, wParam, lParam);
+ case WM_NOTIFY:
+ return forwardNotify(hwnd, uMsg, wParam, lParam);
+ case WM_SIZE:
+ if (GetClientRect(hwnd, &r) == 0)
+ xpanic("error getting client rect for Window in WM_SIZE", GetLastError());
+ containerResize(data, &r);
+ return 0;
+ default:
+ return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ }
+ xmissedmsg("container", "containerWndProc()", uMsg);
+ return 0; /* unreached */
+}
+
+DWORD makeContainerWindowClass(char **errmsg)
+{
+ WNDCLASSW wc;
+
+ ZeroMemory(&wc, sizeof (WNDCLASSW));
+ wc.lpfnWndProc = containerWndProc;
+ wc.hInstance = hInstance;
+ wc.hIcon = hDefaultIcon;
+ wc.hCursor = hArrowCursor;
+ wc.hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
+ if (wc.hbrBackground == NULL) {
+ *errmsg = "error getting hollow brush for container window class";
+ return GetLastError();
+ }
+ wc.lpszClassName = containerclass;
+ if (RegisterClassW(&wc) == 0) {
+ *errmsg = "error registering container window class";
+ return GetLastError();
+ }
+ return 0;
+}
+
+HWND newContainer(void *data)
+{
+ HWND hwnd;
+
+ hwnd = CreateWindowExW(
+ 0,
+ containerclass, L"",
+ WS_CHILD | WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ 100, 100,
+ msgwin, NULL, hInstance, data);
+ if (hwnd == NULL)
+ xpanic("container creation failed", GetLastError());
+ return hwnd;
+}
diff --git a/redo/layout_windows.go b/redo/layout_windows.go
index 7d55a58..3010be9 100644
--- a/redo/layout_windows.go
+++ b/redo/layout_windows.go
@@ -20,15 +20,23 @@ type layout struct {
*sizer
}
+func makeContainerWindowClass() error {
+ var errmsg *C.char
+
+ err := C.makeContainerWindowClass(&errmsg)
+ if err != 0 || errmsg != nil {
+ return fmt.Errorf("%s: %v", C.GoString(errmsg), syscall.Errno(err))
+ }
+ return nil
+}
+
func newLayout(title string, width int, height int, child C.BOOL, control Control) *layout {
l := &layout{
- // hwnd set in WM_CREATE handler
- closing: newEvent(),
sizer: new(sizer),
}
- hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), child, unsafe.Pointer(l))
+ hwnd := C.newContainer(unsafe.Pointer(l))
if hwnd != l.hwnd {
- panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in window/layout (%p) differ", hwnd, l.hwnd))
+ panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in container (%p) differ", hwnd, l.hwnd))
}
l.child = control
l.child.setParent(&controlParent{l.hwnd})
@@ -39,24 +47,15 @@ func (l *layout) setParent(p *controlParent) {
C.controlSetParent(l.hwnd, p.hwnd)
}
-//export storeWindowHWND
-func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) {
+//export storeContainerHWND
+func storeContainerHWND(data unsafe.Pointer, hwnd C.HWND) {
l := (*layout)(data)
l.hwnd = hwnd
}
-//export windowResize
-func windowResize(data unsafe.Pointer, r *C.RECT) {
+//export containerResize
+func containerResize(data unsafe.Pointer, r *C.RECT) {
l := (*layout)(data)
// the origin of the window's content area is always (0, 0), but let's use the values from the RECT just to be safe
l.resize(int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top))
}
-
-//export windowClosing
-func windowClosing(data unsafe.Pointer) {
- l := (*layout)(data)
- close := l.closing.fire()
- if close {
- C.windowClose(l.hwnd)
- }
-}
diff --git a/redo/uitask_windows.go b/redo/uitask_windows.go
index 7913a5c..71b097c 100644
--- a/redo/uitask_windows.go
+++ b/redo/uitask_windows.go
@@ -30,6 +30,9 @@ func uiinit() error {
if err := makeWindowWindowClass(); err != nil {
return fmt.Errorf("error creating Window window class: %v", err)
}
+ if err := makeContainerWindowClass(); err != nil {
+ return fmt.Errorf("error creating container window class: %v", err)
+ }
return nil
}
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 285bbcd..db90e97 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -74,7 +74,7 @@ extern LONG controlTextLength(HWND, LPWSTR);
/* window_windows.c */
extern DWORD makeWindowWindowClass(char **);
-extern HWND newWindow(LPWSTR, int, int, BOOL, void *);
+extern HWND newWindow(LPWSTR, int, int, void *);
extern void windowClose(HWND);
/* common_windows.c */
@@ -98,4 +98,8 @@ extern void tableAppendColumn(HWND, int, LPWSTR);
extern void tableUpdate(HWND, int);
extern void tableAddExtendedStyles(HWND, LPARAM);
+/* container_windows.c */
+extern DWORD makeContainerWindowClass(char **);
+extern HWND newContainer(void *);
+
#endif
diff --git a/redo/window_windows.c b/redo/window_windows.c
index 5ed4de9..9cf0654 100644
--- a/redo/window_windows.c
+++ b/redo/window_windows.c
@@ -60,29 +60,20 @@ DWORD makeWindowWindowClass(char **errmsg)
return 0;
}
-HWND newWindow(LPWSTR title, int width, int height, BOOL child, void *data)
+HWND newWindow(LPWSTR title, int width, int height, void *data)
{
HWND hwnd;
- DWORD style;
- HWND parent;
- style = WS_OVERLAPPEDWINDOW;
- parent = NULL;
- if (child) {
- style = WS_CHILD | WS_VISIBLE;
- parent = msgwin;
- }
hwnd = CreateWindowExW(
0,
windowclass, title,
- style,
+ WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
- parent, NULL, hInstance, data);
+ NULL, NULL, hInstance, data);
if (hwnd == NULL)
xpanic("Window creation failed", GetLastError());
- if (!child)
- calculateBaseUnits(hwnd);
+ calculateBaseUnits(hwnd);
return hwnd;
}
diff --git a/redo/window_windows.go b/redo/window_windows.go
index 3306613..9cf98d0 100644
--- a/redo/window_windows.go
+++ b/redo/window_windows.go
@@ -11,8 +11,12 @@ import (
import "C"
type window struct {
- *layout
+ hwnd C.HWND
shownbefore bool
+
+ closing *event
+
+ *layout
}
func makeWindowWindowClass() error {
@@ -27,13 +31,20 @@ func makeWindowWindowClass() error {
func newWindow(title string, width int, height int, control Control) *window {
w := &window{
- layout: newLayout(title, width, height, C.FALSE, control),
+ // hwnd set in WM_CREATE handler
+ closing: newEvent(),
+ layout: newLayout(control),
+ }
+ hwnd := C.newWindow(toUTF16(title), C.int(width), C.int(height), unsafe.Pointer(w))
+ if hwnd != l.hwnd {
+ panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in Window (%p) differ", hwnd, w.hwnd))
}
// TODO keep?
hresult := C.EnableThemeDialogTexture(w.hwnd, C.ETDT_ENABLE | C.ETDT_USETABTEXTURE)
if hresult != C.S_OK {
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
}
+ w.layout.setParent(&controlParent{w.hwnd})
return w
}
@@ -66,3 +77,26 @@ func (w *window) Close() {
func (w *window) OnClosing(e func() bool) {
w.closing.setbool(e)
}
+
+//export storeWindowHWND
+func storeWindowHWND(data unsafe.Pointer, hwnd C.HWND) {
+ w := (*wiindow)(data)
+ w.hwnd = hwnd
+}
+
+//export windowResize
+func windowResize(data unsafe.Pointer, r *C.RECT) {
+ w := (*window)(data)
+ // the origin of the window's content area is always (0, 0), but let's use the values from the RECT just to be safe
+ // TODO
+ C.moveWindow(w.layout.hwnd, int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top))
+}
+
+//export windowClosing
+func windowClosing(data unsafe.Pointer) {
+ l := (*layout)(data)
+ close := l.closing.fire()
+ if close {
+ C.windowClose(l.hwnd)
+ }
+}