diff options
Diffstat (limited to 'popover')
| -rw-r--r-- | popover/main_windows.c | 227 | ||||
| -rw-r--r-- | popover/popover.c | 174 | ||||
| -rw-r--r-- | popover/popover.h | 30 | ||||
| -rw-r--r-- | popover/popover_unix.c | 117 |
4 files changed, 0 insertions, 548 deletions
diff --git a/popover/main_windows.c b/popover/main_windows.c deleted file mode 100644 index 24c941a..0000000 --- a/popover/main_windows.c +++ /dev/null @@ -1,227 +0,0 @@ -// 9 october 2014 -#include "../wininclude_windows.h" -#include "popover.h" - -// #qo LIBS: user32 kernel32 gdi32 - -// TODO -// - should the parent window appear deactivated? - -HWND popoverWindow; - -void xpanic(char *msg, DWORD err) -{ - printf("%d | %s\n", err, msg); - abort(); -} - -popover *p; - -HRGN makePopoverRegion(HDC dc, LONG width, LONG height) -{ - popoverPoint ppt[20]; - POINT pt[20]; - int i, n; - HRGN region; - - n = popoverMakeFramePoints(p, (intptr_t) width, (intptr_t) height, ppt); - for (i = 0; i < n; i++) { - pt[i].x = (LONG) (ppt[i].x); - pt[i].y = (LONG) (ppt[i].y); - } - - if (BeginPath(dc) == 0) - xpanic("error beginning path for Popover shape", GetLastError()); - if (Polyline(dc, pt, n) == 0) - xpanic("error drawing lines in Popover shape", GetLastError()); - if (EndPath(dc) == 0) - xpanic("error ending path for Popover shape", GetLastError()); - region = PathToRegion(dc); - if (region == NULL) - xpanic("error converting Popover shape path to region", GetLastError()); - return region; -} - -#define msgPopoverPrepareLeftRight (WM_APP+50) -#define msgPopoverPrepareTopBottom (WM_APP+51) - -LRESULT CALLBACK popoverproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - PAINTSTRUCT ps; - HDC dc; - HRGN region; - RECT r; - LONG width; - LONG height; - WINDOWPOS *wp; - HBRUSH brush; - - switch (uMsg) { - case WM_NCPAINT: - if (GetWindowRect(hwnd, &r) == 0) - xpanic("error getting Popover window rect for shape redraw", GetLastError()); - width = r.right - r.left; - height = r.bottom - r.top; - dc = GetWindowDC(hwnd); - if (dc == NULL) - xpanic("error getting Popover window DC for drawing border", GetLastError()); - region = makePopoverRegion(dc, width, height); - // don't call FillRgn(); WM_ERASEBKGND seems to do this to the non-client area for us already :S (TODO confirm) - // TODO arrow is black in wine - brush = (HBRUSH) GetStockObject(BLACK_BRUSH); - if (brush == NULL) - xpanic("error getting Popover border brush", GetLastError()); - if (FrameRgn(dc, region, brush, 1, 1) == 0) - xpanic("error drawing Popover border", GetLastError()); - if (DeleteObject(region) == 0) - xpanic("error deleting Popover shape region", GetLastError()); - if (ReleaseDC(hwnd, dc) == 0) - xpanic("error releasing Popover window DC for shape drawing", GetLastError()); - return 0; - case WM_WINDOWPOSCHANGED: - // this must be here; if it's in WM_NCPAINT weird things happen (see http://stackoverflow.com/questions/26288303/why-is-my-client-rectangle-drawing-behaving-bizarrely-pictures-provided-if-i-t) - wp = (WINDOWPOS *) lParam; - if ((wp->flags & SWP_NOSIZE) == 0) { - dc = GetWindowDC(hwnd); - if (dc == NULL) - xpanic("error getting Popover window DC for reshaping", GetLastError()); - region = makePopoverRegion(dc, wp->cx, wp->cy); - if (SetWindowRgn(hwnd, region, TRUE) == 0) - xpanic("error setting Popover shape", GetLastError()); - // don't delete the region; the window manager owns it now - if (ReleaseDC(hwnd, dc) == 0) - xpanic("error releasing Popover window DC for reshaping", GetLastError()); - } - break; // defer to DefWindowProc() - case WM_NCCALCSIZE: - { - RECT *r = (RECT *) lParam; - NCCALCSIZE_PARAMS *np = (NCCALCSIZE_PARAMS *) lParam; - popoverRect pr; - - if (wParam != FALSE) - r = &np->rgrc[0]; - pr.left = (intptr_t) (r->left); - pr.top = (intptr_t) (r->top); - pr.right = (intptr_t) (r->right); - pr.bottom = (intptr_t) (r->bottom); - popoverWindowSizeToClientSize(p, &pr); - r->left = (LONG) (pr.left); - r->top = (LONG) (pr.top); - r->right = (LONG) (pr.right); - r->bottom = (LONG) (pr.bottom); - return 0; - } - case WM_PAINT: - dc = BeginPaint(hwnd, &ps); - GetClientRect(hwnd, &r); - FillRect(dc, &r, GetSysColorBrush(COLOR_ACTIVECAPTION)); - FrameRect(dc, &r, GetStockPen(WHITE_BRUSH)); - EndPaint(hwnd, &ps); - return 0; - case msgPopoverPrepareLeftRight: - case msgPopoverPrepareTopBottom: - // TODO window edge detection - { - RECT r; - LONG width = 200, height = 200; - popoverRect control; - uintptr_t side; - popoverRect out; - - if (GetWindowRect((HWND) wParam, &r) == 0) - xpanic("error getting window rect of Popover target", GetLastError()); - control.left = (intptr_t) (r.left); - control.top = (intptr_t) (r.top); - control.right = (intptr_t) (r.right); - control.bottom = (intptr_t) (r.bottom); - switch (uMsg) { - case msgPopoverPrepareLeftRight: - side = popoverPointLeft; - break; - case msgPopoverPrepareTopBottom: - side = popoverPointTop; - break; - } - out = popoverPointAt(p, control, (intptr_t) width, (intptr_t) height, side); - if (MoveWindow(hwnd, out.left, out.top, out.right - out.left, out.bottom - out.top, TRUE) == 0) - xpanic("error repositioning Popover", GetLastError()); - } - return 0; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -HWND button; - -LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 100) { - SendMessageW(popoverWindow, msgPopoverPrepareLeftRight, (WPARAM) button, 0); - ShowWindow(popoverWindow, SW_SHOW); - UpdateWindow(popoverWindow); - return 0; - } - break; - case WM_CLOSE: - PostQuitMessage(0); - return 0; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); -} - -int main(int argc, char *argv[]) -{ - WNDCLASSW wc; - HWND mainwin; - MSG msg; - - p = popoverDataNew(NULL); - // TODO null check - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = L"popover"; - wc.lpfnWndProc = popoverproc; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - wc.style = CS_DROPSHADOW | CS_NOCLOSE; - if (RegisterClassW(&wc) == 0) - abort(); - popoverWindow = CreateWindowExW(WS_EX_TOPMOST, - L"popover", L"", - WS_POPUP, - 0, 0, 150, 100, - NULL, NULL, NULL, NULL); - if (popoverWindow == NULL) - abort(); - - ZeroMemory(&wc, sizeof (WNDCLASSW)); - wc.lpszClassName = L"mainwin"; - wc.lpfnWndProc = wndproc; - wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); - if (RegisterClassW(&wc) == 0) - abort(); - mainwin = CreateWindowExW(0, - L"mainwin", L"Main Window", - WS_OVERLAPPEDWINDOW, - 0, 0, 150, 100, - NULL, NULL, NULL, NULL); - if (mainwin == NULL) - abort(); - button = CreateWindowExW(0, - L"button", L"Click Me", - BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, - 20, 20, 100, 40, - mainwin, (HMENU) 100, NULL, NULL); - if (button == NULL) - abort(); - ShowWindow(mainwin, SW_SHOWDEFAULT); - if (UpdateWindow(mainwin) == 0) - abort(); - while (GetMessageW(&msg, NULL, 0, 0) > 0) { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - return 0; -} diff --git a/popover/popover.c b/popover/popover.c deleted file mode 100644 index 2c2bf66..0000000 --- a/popover/popover.c +++ /dev/null @@ -1,174 +0,0 @@ -// 9 october 2014 -#include <stdlib.h> -#include <stdint.h> -#include "popover.h" - -#define ARROWHEIGHT 8 -#define ARROWWIDTH 8 /* should be the same for smooth lines on Windows (TODO is there a better/nicer looking way?) */ - -struct popover { - void *gopopover; - - // a nice consequence of this design is that it allows four arrowheads to jut out at once; in practice only one will ever be used, but hey — simple implementation! - intptr_t arrowLeft; - intptr_t arrowTop; - intptr_t arrowRight; - intptr_t arrowBottom; -}; - -popover *popoverDataNew(void *gopopover) -{ - popover *p; - - p = (popover *) malloc(sizeof (popover)); - if (p != NULL) { - p->gopopover = gopopover; - p->arrowLeft = -1; - p->arrowTop = 20;//TODO-1; - p->arrowRight = -1; - p->arrowBottom = -1; - } - return p; -} - -int popoverMakeFramePoints(popover *p, intptr_t width, intptr_t height, popoverPoint pt[20]) -{ - int n; - intptr_t xmax, ymax; - - n = 0; - - // figure out the xmax and ymax of the box - xmax = width; - if (p->arrowRight >= 0) - xmax -= ARROWWIDTH; - ymax = height; - if (p->arrowBottom >= 0) - ymax -= ARROWHEIGHT; - - // the first point is either at (0,0), (0,arrowHeight), (arrowWidth,0), or (arrowWidth,arrowHeight) - pt[n].x = 0; - if (p->arrowLeft >= 0) - pt[n].x = ARROWWIDTH; - pt[n].y = 0; - if (p->arrowTop >= 0) - pt[n].y = ARROWHEIGHT; - n++; - - // the left side - pt[n].x = pt[n - 1].x; - if (p->arrowLeft >= 0) { - pt[n].y = pt[n - 1].y + p->arrowLeft; - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x; - } - pt[n].y = ymax; - n++; - - // the bottom side - pt[n].y = pt[n - 1].y; - if (p->arrowBottom >= 0) { - pt[n].x = pt[n - 1].x + p->arrowBottom; - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].y = pt[n - 1].y; - } - pt[n].x = xmax; - n++; - - // the right side - pt[n].x = pt[n - 1].x; - if (p->arrowRight >= 0) { - pt[n].y = pt[0].y + p->arrowRight + (ARROWHEIGHT * 2); - n++; - pt[n].x = pt[n - 1].x + ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x; - } - pt[n].y = pt[0].y; - n++; - - // the top side - pt[n].y = pt[n - 1].y; - if (p->arrowTop >= 0) { - pt[n].x = pt[0].x + p->arrowTop + (ARROWWIDTH * 2); - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y - ARROWHEIGHT; - n++; - pt[n].x = pt[n - 1].x - ARROWWIDTH; - pt[n].y = pt[n - 1].y + ARROWHEIGHT; - n++; - pt[n].y = pt[n - 1].y; - } - pt[n].x = pt[0].x; - n++; - - return n; -} - -void popoverWindowSizeToClientSize(popover *p, popoverRect *r) -{ - r->left++; - r->top++; - r->right--; - r->bottom--; - if (p->arrowLeft >= 0) - r->left += ARROWWIDTH; - if (p->arrowRight >= 0) - r->right -= ARROWWIDTH; - if (p->arrowTop >= 0) - r->top += ARROWHEIGHT; - if (p->arrowBottom >= 0) - r->bottom -= ARROWHEIGHT; -} - -// TODO window edge detection -popoverRect popoverPointAt(popover *p, popoverRect control, intptr_t width, intptr_t height, unsigned int side) -{ - intptr_t x, y; - popoverRect out; - - // account for border - width += 2; - height += 2; - p->arrowLeft = -1; - p->arrowRight = -1; - p->arrowTop = -1; - p->arrowBottom = -1; - // TODO right and bottom - switch (side) { - case popoverPointLeft: - width += ARROWWIDTH; - p->arrowLeft = height / 2 - ARROWHEIGHT; - x = control.right; - y = control.top - ((height - (control.bottom - control.top)) / 2); - break; - case popoverPointTop: - height += ARROWHEIGHT; - p->arrowTop = width / 2 - ARROWWIDTH; - x = control.left - ((width - (control.right - control.left)) / 2); - y = control.bottom; - break; - } - out.left = x; - out.top = y; - out.right = x + width; - out.bottom = y + height; - return out; -} diff --git a/popover/popover.h b/popover/popover.h deleted file mode 100644 index 28220e4..0000000 --- a/popover/popover.h +++ /dev/null @@ -1,30 +0,0 @@ -// 11 october 2014 - -typedef struct popover popover; -typedef struct popoverPoint popoverPoint; -typedef struct popoverRect popoverRect; - -struct popoverPoint { - intptr_t x; - intptr_t y; -}; - -struct popoverRect { - intptr_t left; - intptr_t top; - intptr_t right; - intptr_t bottom; -}; - -// note the order: flipping sides is as easy as side ^ 1 -enum { - popoverPointLeft, - popoverPointRight, - popoverPointTop, - popoverPointBottom, -}; - -popover *popoverDataNew(void *); -int popoverMakeFramePoints(popover *, intptr_t, intptr_t, popoverPoint[20]); -void popoverWindowSizeToClientSize(popover *, popoverRect *); -popoverRect popoverPointAt(popover *, popoverRect, intptr_t, intptr_t, unsigned int); diff --git a/popover/popover_unix.c b/popover/popover_unix.c deleted file mode 100644 index 0844844..0000000 --- a/popover/popover_unix.c +++ /dev/null @@ -1,117 +0,0 @@ -// 11 october 2014 -// #qo pkg-config: gtk+-3.0 -#include <gtk/gtk.h> - -#define GOPOPOVER_TYPE (goPopover_get_type()) -#define GOPOPOVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GOPOPOVER_TYPE, goPopover)) -#define IS_GOPOPOVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GOPOPOVER_TYPE)) -#define GOPOPOVER_CLASS(class) (G_TYPE_CHECK_CLASS_CAST((class), GOPOPOVER_TYPE, goPopoverClass)) -#define IS_GOPOPOVER_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE((class), GOPOPOVER_TYPE)) -#define GOPOPOVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GOPOPOVER_TYPE, goPopoverClass)) - -typedef struct goPopover goPopover; -typedef struct goPopoverClass goPopoverClass; - -struct goPopover { - GtkBin parent_instance; - void *gocontainer; - GdkWindow *gdkwin; -}; - -struct goPopoverClass { - GtkBinClass parent_class; -}; - -G_DEFINE_TYPE(goPopover, goPopover, GTK_TYPE_BIN) - -static void goPopover_init(goPopover *p) -{ - gtk_widget_set_has_window(GTK_WIDGET(p), TRUE); -} - -static void goPopover_dispose(GObject *obj) -{ - G_OBJECT_CLASS(goPopover_parent_class)->dispose(obj); -} - -static void goPopover_finalize(GObject *obj) -{ - G_OBJECT_CLASS(goPopover_parent_class)->finalize(obj); -} - -static void goPopover_realize(GtkWidget *widget) -{ - GdkWindowAttr attr; - goPopover *p = GOPOPOVER(widget); - - attr.x = 0; - attr.y = 0; - attr.width = 200; - attr.height = 200; - attr.wclass = GDK_INPUT_OUTPUT; - attr.event_mask = gtk_widget_get_events(GTK_WIDGET(p)) | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; - attr.visual = gtk_widget_get_visual(GTK_WIDGET(p)); - attr.window_type = GDK_WINDOW_CHILD; // GtkPopover does this; TODO what does GtkWindow(GTK_WINDOW_POPUP) do? - p->gdkwin = gdk_window_new(gtk_widget_get_parent_window(GTK_WIDGET(p)), - &attr, GDK_WA_VISUAL); - gtk_widget_set_window(GTK_WIDGET(p), p->gdkwin); - gtk_widget_register_window(GTK_WIDGET(p), p->gdkwin); - gtk_widget_set_realized(GTK_WIDGET(p), TRUE); -} - -static void goPopover_map(GtkWidget *widget) -{ - gdk_window_show(GOPOPOVER(widget)->gdkwin); - GTK_WIDGET_CLASS(goPopover_parent_class)->map(widget); -} - -static void goPopover_unmap(GtkWidget *widget) -{ - gdk_window_hide(GOPOPOVER(widget)->gdkwin); - GTK_WIDGET_CLASS(goPopover_parent_class)->unmap(widget); -} - -static gboolean goPopover_draw(GtkWidget *widget, cairo_t *cr) -{ - GtkStyleContext *context; - - context = gtk_widget_get_style_context(widget); - gtk_render_background(context, cr, 0, 0, 200, 200); - return TRUE; -} - -static void goPopover_class_init(goPopoverClass *class) -{ - G_OBJECT_CLASS(class)->dispose = goPopover_dispose; - G_OBJECT_CLASS(class)->finalize = goPopover_finalize; - GTK_WIDGET_CLASS(class)->realize = goPopover_realize; - GTK_WIDGET_CLASS(class)->map = goPopover_map; - GTK_WIDGET_CLASS(class)->unmap = goPopover_unmap; - GTK_WIDGET_CLASS(class)->draw = goPopover_draw; -} - -void buttonClicked(GtkWidget *button, gpointer data) -{ - GtkWidget *popover; - - popover = g_object_new(GOPOPOVER_TYPE, NULL); - gtk_widget_set_parent(popover, gtk_widget_get_parent(button)); - gtk_widget_show(popover); -} - -int main(void) -{ - GtkWidget *mainwin; - GtkWidget *button; - - gtk_init(NULL, NULL); - mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_resize(GTK_WINDOW(mainwin), 150, 50); - g_signal_connect(mainwin, "destroy", gtk_main_quit, NULL); - button = gtk_button_new_with_label("Click Me"); - g_signal_connect(button, "clicked", G_CALLBACK(buttonClicked), NULL); - gtk_container_add(GTK_CONTAINER(mainwin), button); - gtk_widget_show_all(mainwin); - gtk_main(); - return 0; -} |
