Compare commits

..

44 Commits

Author SHA1 Message Date
IoIxD
30a100fd28 wayland/opengl: set EGL_DEPTH_SIZE to 24 2026-01-03 19:21:03 -07:00
IoIxD
a148b3bedf wayland: use mutexes to ensure that MwLLDestroyImpl never conflicts with wayland events. 2026-01-03 18:27:34 -07:00
IoIxD
bed668b84a wayland: fix misc. crashes on the destruction of widgets 2026-01-02 14:19:48 -07:00
NishiOwO
6183a1ccda update license 2026-01-02 00:24:59 +09:00
IoIxD
f32f6cefc0 wayland: accidentally removed event_loop call from MwLLNextEventImpl 2025-12-30 22:44:04 -07:00
IoIxD
f3683dece3 undo HAS_OPENGL stuff 2025-12-30 22:38:01 -07:00
IoIxD
808495cccf wayland: misc fixes 2025-12-30 22:28:36 -07:00
IoIxD
6946c1eaf3 wayland: opengl support 2025-12-30 22:26:19 -07:00
IoIxD
029e62d765 wayland: opengl 2025-12-30 20:30:29 -07:00
IoIxD
a03065ae52 wayland: forgot to commit .h 2025-12-30 19:16:01 -07:00
IoIxD
324257c43f wayland: no pthreads needed 2025-12-30 19:15:33 -07:00
IoIxD
afecb04848 clipboard: don't set clipboard after pasting 2025-12-30 17:14:57 -07:00
IoIxD
bed63dd245 clipboard: fix syntax 2025-12-30 17:14:39 -07:00
IoIxD
67bd6029af wayland: finish clipboard 2025-12-30 17:12:12 -07:00
NishiOwO
72820e87f1 rename clipboard_received to clipboard 2025-12-31 04:35:10 +09:00
NishiOwO
d3147ac087 format 2025-12-31 04:29:27 +09:00
NishiOwO
4bdda59693 better api for clipboard 2025-12-31 04:29:13 +09:00
NishiOwO
823c865791 handle WM_DELETE_WINDOW better 2025-12-31 00:48:44 +09:00
NishiOwO
3f9125d1ae fix 2025-12-30 23:54:30 +09:00
NishiOwO
549d235893 better 2025-12-28 21:56:45 +09:00
NishiOwO
0daa527b1d fix 2025-12-28 18:03:37 +09:00
NishiOwO
0ca7f6ed8a dispatch children_update 2025-12-28 17:41:11 +09:00
NishiOwO
e895e96941 introduce MwNleftPadding to label 2025-12-25 15:39:54 +09:00
NishiOwO
0d79141a49 tiny fix 2025-12-25 04:21:33 +09:00
NishiOwO
c80987ffe4 better 2025-12-25 04:18:12 +09:00
NishiOwO
d3a7b0a01d oops 2025-12-25 04:03:05 +09:00
NishiOwO
e77c4f3c38 add MwNleftPadding to SubMenu 2025-12-25 03:56:04 +09:00
NishiOwO
22b4737c33 better separator 2025-12-25 02:27:41 +09:00
NishiOwO
509351a0a0 fix submenu 2025-12-25 00:19:27 +09:00
NishiOwO
86effbdfd7 fix 2025-12-24 22:52:26 +09:00
NishiOwO
7b47524286 improve submenu 2025-12-24 13:56:08 +09:00
NishiOwO
c8e7f58230 wrong 2025-12-23 22:11:22 +09:00
NishiOwO
9ea54b4f88 format 2025-12-23 22:08:55 +09:00
NishiOwO
55f82e4fbc update 2025-12-23 22:08:49 +09:00
NishiOwO
a23016bc05 yes 2025-12-23 18:14:00 +09:00
NishiOwO
df99e66d87 tiny fix 2025-12-23 18:10:50 +09:00
NishiOwO
e9fd2705d4 fix 2025-12-21 23:05:42 +09:00
NishiOwO
a824b4fc44 oops 2025-12-21 23:04:53 +09:00
NishiOwO
c7c8f236b0 yes 2025-12-21 23:03:33 +09:00
NishiOwO
bdc67d6369 text shadow 2025-12-21 23:02:02 +09:00
NishiOwO
873c75b882 fix 2025-12-21 22:21:10 +09:00
NishiOwO
e44eaa2c16 fix 2025-12-21 22:02:33 +09:00
NishiOwO
0d281c09ce i will work on vms port at some point 2025-12-21 20:25:57 +09:00
NishiOwO
2b30a06ecf wip VMS port 2025-12-21 19:29:05 +09:00
45 changed files with 1421 additions and 382 deletions

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@ examples/*/*.exe
!examples/*/
!examples/*.*
!examples/*/*.*
*.exe
*.o
*.so
*.dll

View File

@@ -195,7 +195,6 @@ target_compile_definitions(
_MILSKO
)
include(GNUInstallDirs)
install(
TARGETS Mw
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

View File

@@ -1,4 +1,4 @@
Copyright (c) 2025, Pyrite development team
Copyright (c) 2025-2026, Pyrite development team
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,7 +1,6 @@
#define _MILSKO
#include <Mw/Milsko.h>
MwWidget window, button, text;
MwWidget window, instructions, text;
void resize(MwWidget handle, void* user_data, void* call_data) {
unsigned int w, h, mh;
@@ -12,7 +11,7 @@ void resize(MwWidget handle, void* user_data, void* call_data) {
w = MwGetInteger(handle, MwNwidth);
h = MwGetInteger(handle, MwNheight);
MwVaApply(button,
MwVaApply(instructions,
MwNy, 50 + mh,
MwNwidth, w - 50 * 2,
MwNheight, h - 125 - 50 * 3,
@@ -24,40 +23,34 @@ void resize(MwWidget handle, void* user_data, void* call_data) {
MwNheight, h - 125 - 50 * 3,
NULL);
}
void clipboard(MwWidget handle, void* user_data, void* call_data) {
char* clipboard = call_data;
void handler(MwWidget handle, void* user_data, void* call_data) {
(void)handle;
(void)user_data;
(void)call_data;
char* clipboard;
clipboard = MwLLGetClipboard(handle->lowlevel);
if(clipboard != NULL) {
MwVaApply(text, MwNtext, clipboard);
MwForceRender(text);
}
resize(window, NULL, NULL);
MwForceRender(window);
}
int main() {
MwMenu m, m2;
MwLibraryInit();
window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 400, 400,
MwNtitle, "clipboard",
NULL);
button = MwVaCreateWidget(MwButtonClass, "button", window, 50, 50, 300, 125,
MwNtext, "get clipboard contents",
instructions = MwVaCreateWidget(MwLabelClass, "button", window, 50, 50, 300, 125,
MwNtext, "clipboard contents will show up below.",
NULL);
text = MwVaCreateWidget(MwLabelClass, "label", window, 50, 200, 300, 125,
MwNtext, "",
NULL);
MwAddUserHandler(window, MwNresizeHandler, resize, NULL);
MwAddUserHandler(button, MwNactivateHandler, handler, NULL);
MwAddUserHandler(window, MwNclipboardHandler, clipboard, NULL);
resize(window, NULL, NULL);

View File

@@ -52,6 +52,11 @@ MWDECL const char* MwDefaultDarkSubBackground;
*/
MWDECL const char* MwDefaultDarkSubForeground;
/*!
* @brief Default shadow difference
*/
MWDECL const int MwDefaultShadow;
/*!
* @brief Gets default border width
* @param handle Widget

View File

@@ -147,6 +147,7 @@ struct _MwLLHandler {
void (*key_released)(MwLL handle, void* data);
void (*focus_in)(MwLL handle, void* data);
void (*focus_out)(MwLL handle, void* data);
void (*clipboard)(MwLL handle, void* data);
};
#ifdef __cplusplus
@@ -203,7 +204,7 @@ MWDECL void (*MwLLFocus)(MwLL handle);
MWDECL void (*MwLLGrabPointer)(MwLL handle, int toggle);
MWDECL void (*MwLLSetClipboard)(MwLL handle, const char* text);
MWDECL char* (*MwLLGetClipboard)(MwLL handle);
MWDECL void (*MwLLGetClipboard)(MwLL handle);
MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point);
MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect);

View File

@@ -21,6 +21,7 @@ struct _MwLLGDI {
int grabbed;
int force_render;
int get_clipboard;
};
struct _MwLLGDIColor {

View File

@@ -16,6 +16,7 @@
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include <cairo/cairo.h>
#include <pthread.h>
MWDECL int MwLLWaylandCallInit(void);
@@ -97,6 +98,21 @@ enum _MwLLWaylandType {
MWLL_WAYLAND_POPUP,
};
typedef struct wl_clipboard_device_context {
union {
struct wl_data_device* wl;
struct zwp_primary_selection_device_v1* zwp;
} device;
union {
struct wl_data_offer* wl;
struct zwp_primary_selection_offer_v1* zwp;
} offer;
MwLL ll;
struct wl_seat* seat;
MwU32 capabilities;
} wl_clipboard_device_context_t;
struct _MwLLWayland {
struct _MwLLCommon common;
@@ -124,6 +140,8 @@ struct _MwLLWayland {
wayland_protocol_t* value;
}* wl_protocol_map;
MwBool always_render;
struct wl_display* display;
struct wl_registry* registry;
struct wl_compositor* compositor;
@@ -131,12 +149,29 @@ struct _MwLLWayland {
struct wl_region* region;
struct wl_output* output;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
MwU32 pointer_serial;
/* clipboard related stuff.
* Note that unlike most interfaces, we don't keep zwp_primary_selection stuff in a wayland_protocol_t because we use wl_data_device as a fallback and want to have it share memory space.*/
MwBool events_pending;
MwBool test;
union {
struct wl_data_device_manager* wl;
struct zwp_primary_selection_device_manager_v1* zwp;
} clipboard_manager;
union {
struct wl_data_source* wl;
struct zwp_primary_selection_source_v1* zwp;
} clipboard_source;
char* clipboard_buffer;
MwBool supports_zwp;
uint32_t clipboard_serial;
wl_clipboard_device_context_t** clipboard_devices;
struct wl_pointer* pointer;
MwU32 pointer_serial;
struct wl_keyboard* keyboard;
MwU32 keyboard_serial;
MwU64 events_pending;
MwU32 mod_state;
@@ -149,10 +184,20 @@ struct _MwLLWayland {
MwLL parent;
MwBool force_render;
MwBool disabled;
struct _MwLLWaylandShmBuffer framebuffer;
struct _MwLLWaylandShmBuffer cursor;
struct _MwLLWaylandShmBuffer* icon;
/*
Events mutex. Any time a keyboard/mouse event happens, we try to lock this for 100 milliseconds, then give up if we can't do it. This is used in conjunction with some code in the MwLLDestroyImpl to make sure that destroy is NEVER interferes with an ongoing event.
IOI_XD: This sounds like a hilariously rare edge case, so it's almost funnier that this happened with 100% certainty for me and I spent day(s) trying to figure out what was happening. */
pthread_mutex_t eventsMutex;
cairo_surface_t* cs;
cairo_t* cairo;
};

View File

@@ -29,6 +29,7 @@ struct _MwLLX11 {
GC gc;
Colormap colormap;
Atom wm_delete;
Atom wm_protocols;
XIM xim;
XIC xic;

View File

@@ -38,6 +38,7 @@
#define MwNbitmapFont "IbitmapFont"
#define MwNsevenSegment "IsevenSegment"
#define MwNlength "Ilength"
#define MwNforceInverted "IforceInverted"
#define MwNtitle "Stitle"
#define MwNtext "Stext"
@@ -70,5 +71,6 @@
#define MwNdirectoryChosenHandler "CdirectoryChosen" /* char* */
#define MwNcolorChosenHandler "CcolorChosen" /* MwRGB* */
#define MwNdrawHandler "Cdraw" /* NULL */
#define MwNclipboardHandler "Cclipboard" /* char* */
#endif

View File

@@ -39,6 +39,7 @@ typedef void (*MwHandlerChildrenProp)(MwWidget handle, MwWidget child, const cha
typedef void (*MwHandlerKey)(MwWidget handle, int key);
typedef void (*MwHandlerMouse)(MwWidget handle, void* ptr);
typedef void (*MwHandlerExecute)(MwWidget handle, const char* name, void* out, va_list args);
typedef void (*MwHandlerClipboardReceived)(MwWidget handle, const char* data);
typedef void (*MwUserHandler)(MwWidget handle, void* user_data, void* call_data);
typedef void (*MwErrorHandler)(int code, const char* message, void* user_data);
@@ -108,6 +109,7 @@ struct _MwMenu {
int keep;
MwWidget wsub;
MwMenu* sub;
void* opaque;
};
struct _MwEntry {
@@ -210,11 +212,11 @@ struct _MwClass {
MwHandler resize;
MwHandler children_update;
MwHandlerChildrenProp children_prop_change;
MwHandlerClipboardReceived clipboard;
void* reserved1;
void* reserved2;
void* reserved3;
void* reserved4;
void* reserved5;
};
#endif

View File

@@ -29,6 +29,16 @@ MwInline void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point, int
MwVaWidgetExecute(handle, "mwSubMenuAppear", NULL, menu, point, diff_calc);
}
/*!
* @brief Calculates the size of submenu
* @param handle Handle
* @param menu Menu
* @param rect Size
*/
MwInline void MwSubMenuGetSize(MwWidget handle, MwMenu menu, MwRect* rect) {
MwVaWidgetExecute(handle, "mwSubMenuGetSize", NULL, menu, rect);
}
#ifdef __cplusplus
}
#endif

View File

@@ -52,6 +52,7 @@
- MwNratio
- MwNfixedSize
- MwNbitmapFont
- MwNforceInverted
Integer properties must be prefixed with I.
String properties must be prefixed with S.
@@ -91,6 +92,7 @@
<integer name="bitmapFont" />
<integer name="sevenSegment" />
<integer name="length" />
<integer name="forceInverted" />
<string name="title" />
<string name="text" />
@@ -120,6 +122,7 @@
<handler name="directoryChosen" />
<handler name="colorChosen" />
<handler name="draw" />
<handler name="clipboard" />
</properties>
<enumerations>
<enumeration name="MwDIRECTION">
@@ -542,6 +545,7 @@
<property name="bold" />
<property name="sevenSegment" />
<property name="length" />
<property name="leftPadding" />
</properties>
<functions>
<function name="SetSevenSegment">
@@ -638,6 +642,9 @@
</functions>
</widget>
<widget name="SubMenu">
<properties>
<property name="leftPadding" />
</properties>
<functions>
<function name="Appear">
<arguments>

View File

@@ -32,6 +32,10 @@ if (grep(/^wayland$/, @backends)) {
add_cflags(`pkg-config --cflags cairo wayland-client xkbcommon`);
add_libs(`pkg-config --libs cairo wayland-client xkbcommon`);
if (param_get("opengl")) {
add_libs(`pkg-config --libs egl wayland-egl`);
}
scan_wayland_protocol("stable", "xdg-shell", "");
scan_wayland_protocol("stable", "tablet", "-v2");
scan_wayland_protocol("staging", "xdg-toplevel-icon", "-v1");
@@ -39,7 +43,7 @@ if (grep(/^wayland$/, @backends)) {
scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1");
scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1");
$gl_libs = "-lEGL -lwayland-egl lGL -lGLU";
$gl_libs = "-lGL -lGLU";
}
if (param_get("stb-image")) {
@@ -48,6 +52,7 @@ if (param_get("stb-image")) {
if (param_get("stb-truetype")) {
add_cflags("-DUSE_STB_TRUETYPE");
}
if (param_get("freetype2")) {
add_cflags("-DUSE_FREETYPE2");
if ($cross) {

View File

@@ -237,6 +237,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
r->common.copy_buffer = 1;
r->common.type = MwLLBackendGDI;
r->gdi.get_clipboard = 1;
r->gdi.force_render = 0;
r->gdi.grabbed = 0;
r->gdi.hWnd = CreateWindow("milsko", "Milsko", parent == NULL ? (WS_OVERLAPPEDWINDOW) : (WS_CHILD | WS_VISIBLE), x == MwDEFAULT ? CW_USEDEFAULT : x, y == MwDEFAULT ? CW_USEDEFAULT : y, width, height, parent == NULL ? NULL : parent->gdi.hWnd, 0, wc.hInstance, NULL);
@@ -383,6 +384,7 @@ static int MwLLPendingImpl(MwLL handle) {
(void)handle;
if(handle->gdi.get_clipboard) return 1;
return PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE) ? 1 : 0;
}
@@ -391,6 +393,24 @@ static void MwLLNextEventImpl(MwLL handle) {
(void)handle;
if(handle->gdi.get_clipboard) {
HGLOBAL hg;
if(OpenClipboard(handle->gdi.hWnd) != 0 && (hg = GetClipboardData(CF_TEXT)) != NULL) {
char* txt = malloc(GlobalSize(hg));
char* clp = GlobalLock(hg);
strcpy(txt, clp);
GlobalUnlock(hg);
CloseClipboard();
MwLLDispatch(handle, clipboard, txt);
free(txt);
}
handle->gdi.get_clipboard = 0;
}
while(PeekMessage(&msg, handle->gdi.hWnd, 0, 0, PM_NOREMOVE)) {
GetMessage(&msg, handle->gdi.hWnd, 0, 0);
TranslateMessage(&msg);
@@ -697,21 +717,8 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
}
}
static char* MwLLGetClipboardImpl(MwLL handle) {
HGLOBAL hg;
char* r = NULL;
if(OpenClipboard(handle->gdi.hWnd) != 0 && (hg = GetClipboardData(CF_TEXT)) != NULL) {
char* lock;
r = malloc(GlobalSize(hg));
lock = GlobalLock(hg);
strcpy(r, lock);
GlobalUnlock(hg);
CloseClipboard();
}
return r;
static void MwLLGetClipboardImpl(MwLL handle) {
handle->gdi.get_clipboard = 1; /* nishi: we do this to make clipboard api work similar to other backends */
}
static void MwLLMakeToolWindowImpl(MwLL handle) {

View File

@@ -10,11 +10,9 @@
#include <unistd.h>
/* TODO:
* - MwLLSetClipboardImpl
* - MwLLGrabPointerImpl
* - MwLLMakePopupImpl
* - MwLLShowImpl
* - MwLLDetachImpl
*/
/* TODO: find out what FreeBSD and such wants us to include */
@@ -47,7 +45,7 @@ static void new_protocol(void* data, struct wl_registry* registry,
wayland_protocol_callback_table_t* cb = shget(wayland->wl_protocol_setup_map, interface);
if(cb != NULL) {
char* inter = malloc(strlen(interface));
char* inter = malloc(strlen(interface) + 1);
strcpy(inter, interface);
shput(wayland->wl_protocol_map, inter, cb->setup(name, data));
} else {
@@ -62,78 +60,278 @@ static void protocol_removed(void* data,
printf("%d destroyed\n", name);
};
static void offer_offer(void* data,
struct zwp_primary_selection_offer_v1* zwp_primary_selection_offer_v1,
/* Flush Wayland events */
static void wl_flush(MwLL handle) {
struct pollfd pfd;
int rc;
pfd.fd = wl_display_get_fd(handle->wayland.display);
pfd.events = POLLIN;
while(MwTRUE) {
rc = wl_display_flush(handle->wayland.display);
if(errno != EAGAIN || rc != -1) {
break;
}
if(poll(&pfd, 1, -1) == -1) {
break;
}
}
}
static void wl_offer(void* data,
struct wl_data_offer* wl_data_offer,
const char* mime_type) {
wl_clipboard_device_context_t* self = data;
wl_data_offer_accept(wl_data_offer, self->ll->wayland.clipboard_serial, mime_type);
};
struct zwp_primary_selection_offer_v1_listener offer_listener = {
.offer = offer_offer,
struct wl_data_offer_listener offer_listener = {
.offer = wl_offer,
};
typedef struct primary_selection_device_context {
struct zwp_primary_selection_device_v1* device;
struct zwp_primary_selection_offer_v1* offer;
} primary_selection_device_context_t;
static void wl_data_device_data_offer(void* data,
struct wl_data_device* wl_data_device,
struct wl_data_offer* offer) {
wl_clipboard_device_context_t* self = data;
typedef struct primary_selection_context {
struct zwp_primary_selection_device_manager_v1* manager;
/* stored seperately of the listeners because it's not a pointer and it gets assigned to data devices dynamically. */
struct zwp_primary_selection_device_v1_listener listener;
wl_data_offer_add_listener(offer, &offer_listener, data);
struct zwp_primary_selection_source_v1* source;
primary_selection_device_context_t** devices;
} primary_selection_context_t;
self->offer.wl = offer;
};
static void primary_selection_data_offer(void* data,
static void wl_data_device_enter(void* data,
struct wl_data_device* wl_data_device,
uint32_t serial,
struct wl_surface* surface,
wl_fixed_t x,
wl_fixed_t y,
struct wl_data_offer* id) {
MwLL self = data;
self->wayland.clipboard_serial = serial;
};
static void wl_data_device_leave(void* data,
struct wl_data_device* wl_data_device) {
wl_data_device_destroy(wl_data_device);
};
static void wl_data_device_motion(void* data,
struct wl_data_device* wl_data_device,
uint32_t time,
wl_fixed_t x,
wl_fixed_t y) {
};
static void wl_data_device_drop(void* data,
struct wl_data_device* wl_data_device) {
};
static void wl_data_device_selection(void* data,
struct wl_data_device* wl_data_device,
struct wl_data_offer* id) {
};
struct wl_data_device_listener wl_data_device_listener = {
.data_offer = wl_data_device_data_offer,
.enter = wl_data_device_enter,
.leave = wl_data_device_leave,
.motion = wl_data_device_motion,
.drop = wl_data_device_drop,
.selection = wl_data_device_selection,
};
static void zwp_primary_selection_device_v1_data_offer(void* data,
struct zwp_primary_selection_device_v1* zwp_primary_selection_device_v1,
struct zwp_primary_selection_offer_v1* offer) {
struct primary_selection_device_context* self = data;
zwp_primary_selection_offer_v1_add_listener(offer, &offer_listener, data);
wl_clipboard_device_context_t* self = data;
self->offer = offer;
self->offer.zwp = offer;
};
static void primary_selection_selection(void* data,
static void zwp_primary_selection_device_v1_selection(void* data,
struct zwp_primary_selection_device_v1* zwp_primary_selection_device_v1,
struct zwp_primary_selection_offer_v1* id) {
};
struct zwp_primary_selection_device_v1_listener zwp_primary_selection_device_v1_listener = {
.data_offer = zwp_primary_selection_device_v1_data_offer,
.selection = zwp_primary_selection_device_v1_selection,
};
static void wl_clipboard_read(wl_clipboard_device_context_t* ctx) {
int fds[2];
fd_set set;
char* buf = NULL;
struct timeval timeout;
int rc = 0;
int n;
if(pipe(fds) != 0) {
return;
}
FD_ZERO(&set);
FD_SET(fds[0], &set);
timeout.tv_sec = 0;
timeout.tv_usec = 100;
if(ctx->ll->wayland.supports_zwp) {
zwp_primary_selection_offer_v1_receive(ctx->offer.zwp, "text/plain", fds[1]);
} else {
wl_data_offer_receive(ctx->offer.wl, "text/plain", fds[1]);
}
close(fds[1]);
wl_flush(ctx->ll);
wl_display_roundtrip(ctx->ll->wayland.display);
while(MwTRUE) {
char ch;
rc = select(fds[0] + 1, &set, NULL, NULL, &timeout);
if(rc <= 0) {
break;
} else {
char b;
ssize_t n = read(fds[0], &b, sizeof(b));
if(n <= 0) {
break;
}
arrpush(buf, b);
}
}
arrpush(buf, 0);
close(fds[0]);
MwLLDispatch(ctx->ll, clipboard, buf);
arrfree(buf);
}
static void wl_data_source_listener_target(void* data,
struct wl_data_source* wl_data_source,
const char* mime_type) {
};
static void wl_data_source_listener_send(void* data,
struct wl_data_source* wl_data_source,
const char* mime_type,
int32_t fd) {
MwLL self = data;
if(self->wayland.clipboard_buffer != NULL) {
write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer));
close(fd);
self->wayland.events_pending = 1;
}
};
static void wl_data_source_listener_cancelled(void* data,
struct wl_data_source* wl_data_source);
struct wl_data_source_listener wl_data_source_listener = {
.target = wl_data_source_listener_target,
.send = wl_data_source_listener_send,
.cancelled = wl_data_source_listener_cancelled,
};
static void wl_data_source_listener_cancelled(void* data,
struct wl_data_source* wl_data_source) {
MwLL self = data;
wl_data_source_destroy(wl_data_source);
self->wayland.clipboard_source.wl = wl_data_device_manager_create_data_source(self->wayland.clipboard_manager.wl);
wl_data_source_offer(self->wayland.clipboard_source.wl, "text/plain");
wl_data_source_offer(self->wayland.clipboard_source.wl, "text/plain;charset=utf-8");
wl_data_source_offer(self->wayland.clipboard_source.wl, "TEXT");
wl_data_source_offer(self->wayland.clipboard_source.wl, "STRING");
wl_data_source_offer(self->wayland.clipboard_source.wl, "UTF8_STRING");
wl_data_source_add_listener(self->wayland.clipboard_source.wl, &wl_data_source_listener, self);
};
static void zwp_primary_selection_source_v1_send(void* data,
struct zwp_primary_selection_source_v1* wl_data_source,
const char* mime_type,
int32_t fd) {
MwLL self = data;
if(self->wayland.clipboard_buffer != NULL) {
write(fd, self->wayland.clipboard_buffer, strlen(self->wayland.clipboard_buffer));
close(fd);
self->wayland.events_pending = 1;
}
};
static void zwp_primary_selection_source_v1_cancelled(void* data,
struct zwp_primary_selection_source_v1* wl_data_source) {
MwLL self = data;
zwp_primary_selection_source_v1_destroy(self->wayland.clipboard_source.zwp);
self->wayland.clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(self->wayland.clipboard_manager.zwp);
zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "text/plain");
zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "text/plain;charset=utf-8");
zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "TEXT");
zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "STRING");
zwp_primary_selection_source_v1_offer(self->wayland.clipboard_source.zwp, "UTF8_STRING");
};
struct zwp_primary_selection_source_v1_listener zwp_primary_selection_source_v1_listener = {
.send = zwp_primary_selection_source_v1_send,
.cancelled = zwp_primary_selection_source_v1_cancelled,
};
/* wl_data_device_manager setup function */
static wayland_protocol_t* wl_data_device_manager_setup(MwU32 name, struct _MwLLWayland* wayland) {
wayland->clipboard_manager.wl = wl_registry_bind(wayland->registry, name, &wl_data_device_manager_interface, 2);
wayland->clipboard_source.wl = wl_data_device_manager_create_data_source(wayland->clipboard_manager.wl);
wl_data_source_offer(wayland->clipboard_source.wl, "text/plain");
wl_data_source_offer(wayland->clipboard_source.wl, "text/plain;charset=utf-8");
wl_data_source_offer(wayland->clipboard_source.wl, "TEXT");
wl_data_source_offer(wayland->clipboard_source.wl, "STRING");
wl_data_source_offer(wayland->clipboard_source.wl, "UTF8_STRING");
wl_data_source_add_listener(wayland->clipboard_source.wl, &wl_data_source_listener, wayland);
return NULL;
}
static void wl_data_device_manager_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
if(wayland->clipboard_manager.wl != NULL && !wayland->supports_zwp) {
wl_data_device_manager_destroy(wayland->clipboard_manager.wl);
wl_data_source_destroy(wayland->clipboard_source.wl);
wayland->clipboard_manager.wl = NULL;
}
}
/* zwp_primary_selection_device_manager_v1 setup function */
static wayland_protocol_t* zwp_primary_selection_device_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) {
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
primary_selection_context_t* context = malloc(sizeof(primary_selection_context_t));
if(wayland->clipboard_manager.wl != NULL) {
wl_data_device_manager_interface_destroy(wayland, NULL);
}
context->manager = wl_registry_bind(wayland->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
wayland->clipboard_manager.zwp = wl_registry_bind(wayland->registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
struct zwp_primary_selection_device_manager_v1* device;
context->listener.data_offer = primary_selection_data_offer;
context->listener.selection = primary_selection_selection;
wayland->clipboard_source.zwp = zwp_primary_selection_device_manager_v1_create_source(wayland->clipboard_manager.zwp);
context->source = zwp_primary_selection_device_manager_v1_create_source(context->manager);
zwp_primary_selection_source_v1_offer(wayland->clipboard_source.zwp, "text/plain");
zwp_primary_selection_source_v1_offer(wayland->clipboard_source.zwp, "text/plain;charset=utf-8");
zwp_primary_selection_source_v1_offer(wayland->clipboard_source.zwp, "TEXT");
zwp_primary_selection_source_v1_offer(wayland->clipboard_source.zwp, "STRING");
zwp_primary_selection_source_v1_offer(wayland->clipboard_source.zwp, "UTF8_STRING");
context->devices = NULL;
zwp_primary_selection_source_v1_add_listener(wayland->clipboard_source.zwp, &zwp_primary_selection_source_v1_listener, wayland);
proto->context = context;
proto->listener = NULL;
wayland->supports_zwp = MwTRUE;
return proto;
return NULL;
}
static void zwp_primary_selection_device_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
primary_selection_context_t* context = data->context;
int i;
return;
zwp_primary_selection_device_manager_v1_destroy(context->manager);
zwp_primary_selection_device_manager_v1_destroy(wayland->clipboard_manager.zwp);
for(i = 0; i < arrlen(context->devices); i++) {
primary_selection_device_context_t* device = context->devices[i];
// zwp_primary_selection_device_v1_destroy(device->device);
// zwp_primary_selection_offer_v1_destroy(device->offer);
free(device);
}
arrfree(context->devices);
zwp_primary_selection_source_v1_destroy(context->source);
zwp_primary_selection_source_v1_destroy(wayland->clipboard_source.zwp);
free(data->listener);
}
@@ -143,9 +341,17 @@ static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 seria
struct wl_surface* surface, wl_fixed_t surface_x,
wl_fixed_t surface_y) {
MwLL self = data;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
self->wayland.pointer_serial = serial;
wl_pointer_set_cursor(wl_pointer, serial, self->wayland.cursor.surface, 0, 0);
pthread_mutex_unlock(&self->wayland.eventsMutex);
};
/* `wl_pointer.leave` callback */
@@ -159,12 +365,20 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
MwLL self = data;
MwLLMouse p;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
self->wayland.cur_mouse_pos.x = wl_fixed_to_double(surface_x);
self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y);
p.point = self->wayland.cur_mouse_pos;
MwLLDispatch(self, move, &p);
self->wayland.events_pending = MwTRUE;
self->wayland.events_pending += 1;
pthread_mutex_unlock(&self->wayland.eventsMutex);
/*timed_redraw(self, time, 50, &self->wayland.cooldown_timer);*/
};
@@ -173,6 +387,13 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) {
MwLL self = data;
MwLLMouse p;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
p.point = self->wayland.cur_mouse_pos;
if(p.point.x > self->wayland.x && p.point.x < self->wayland.x + self->wayland.ww && p.point.y > self->wayland.y && p.point.y < self->wayland.y + self->wayland.wh) {
switch(button) {
@@ -181,6 +402,10 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri
break;
case BTN_MIDDLE:
p.button = MwLLMouseMiddle;
for(int i = 0; i < arrlen(self->wayland.clipboard_devices); i++) {
wl_clipboard_read(
self->wayland.clipboard_devices[i]);
}
break;
case BTN_RIGHT:
p.button = MwLLMouseRight;
@@ -196,8 +421,11 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 seri
}
}
if(!self->wayland.always_render) {
MwLLDispatch(self, draw, NULL);
self->wayland.events_pending = MwTRUE;
self->wayland.events_pending += 1;
}
pthread_mutex_unlock(&self->wayland.eventsMutex);
};
/* `wl_pointer.axis` callback */
@@ -233,8 +461,6 @@ static void keyboard_keymap(void* data,
close(fd);
struct xkb_state* xkb_state = xkb_state_new(xkb_keymap);
xkb_keymap_unref(wayland->xkb_keymap);
xkb_state_unref(wayland->xkb_state);
wayland->xkb_keymap = xkb_keymap;
wayland->xkb_state = xkb_state;
@@ -248,8 +474,18 @@ static void keyboard_enter(void* data,
struct wl_surface* surface,
struct wl_array* keys) {
MwLL self = data;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
self->wayland.keyboard_serial = serial;
MwLLDispatch(self, focus_in, NULL);
self->wayland.events_pending = MwTRUE;
self->wayland.events_pending += 1;
pthread_mutex_unlock(&self->wayland.eventsMutex);
};
/* `wl_keyboard.leave` callback */
@@ -258,8 +494,17 @@ static void keyboard_leave(void* data,
MwU32 serial,
struct wl_surface* surface) {
MwLL self = data;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
MwLLDispatch(self, focus_out, NULL);
self->wayland.events_pending = MwTRUE;
self->wayland.events_pending += 1;
pthread_mutex_unlock(&self->wayland.eventsMutex);
};
/* `wl_keyboard.key` callback */
@@ -270,6 +515,12 @@ static void keyboard_key(void* data,
MwU32 key,
MwU32 state) {
MwLL self = data;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
struct _MwLLWaylandTopLevel* wayland = self->wayland.toplevel;
xkb_layout_index_t layout;
@@ -334,11 +585,19 @@ static void keyboard_key(void* data,
key = sym;
}
if((self->wayland.mod_state & 4) == 4) {
/* clipboard paste */
if(key == 'V') {
for(int i = 0; i < arrlen(self->wayland.clipboard_devices); i++) {
wl_clipboard_read(
self->wayland.clipboard_devices[i]);
}
}
key |= MwLLControlMask;
}
if((self->wayland.mod_state & 8) == 8) {
key |= MwLLAltMask;
}
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
MwLLDispatch(self, key, &key);
} else {
@@ -346,7 +605,13 @@ static void keyboard_key(void* data,
}
}
}
self->wayland.events_pending = MwTRUE;
if(!self->wayland.always_render) {
MwLLDispatch(self, draw, NULL);
self->wayland.events_pending += 1;
}
pthread_mutex_unlock(&self->wayland.eventsMutex);
};
/* `wl_keyboard.modifiers` callback */
@@ -358,10 +623,18 @@ static void keyboard_modifiers(void* data,
MwU32 mods_locked,
MwU32 group) {
MwLL self = data;
struct timespec t;
t.tv_nsec = 100;
if(pthread_mutex_timedlock(&self->wayland.eventsMutex, &t) != 0) {
return;
};
self->wayland.mod_state = 0;
self->wayland.mod_state |= mods_depressed;
self->wayland.mod_state |= mods_locked;
pthread_mutex_unlock(&self->wayland.eventsMutex);
};
struct wl_keyboard_listener keyboard_listener = {
@@ -380,6 +653,8 @@ wl_seat_name(void* data, struct wl_seat* wl_seat, const char* name) {};
static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
MwU32 capabilities) {
MwLL self = data;
wl_clipboard_device_context_t* device_ctx = malloc(sizeof(wl_clipboard_device_context_t));
if(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
self->wayland.keyboard = wl_seat_get_keyboard(wl_seat);
wl_keyboard_add_listener(self->wayland.keyboard, &keyboard_listener, data);
@@ -389,19 +664,23 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat,
wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data);
}
/* primary selection support */
if(WAYLAND_GET_INTERFACE(self->wayland, zwp_primary_selection_device_manager_v1) != NULL) {
primary_selection_context_t* primary_selection = WAYLAND_GET_INTERFACE(self->wayland, zwp_primary_selection_device_manager_v1)->context;
primary_selection_device_context_t* device_ctx = malloc(sizeof(primary_selection_device_context_t));
if(self->wayland.clipboard_manager.wl != NULL) {
if(self->wayland.supports_zwp) {
device_ctx->device.zwp = zwp_primary_selection_device_manager_v1_get_device(self->wayland.clipboard_manager.zwp, wl_seat);
} else {
device_ctx->device.wl = wl_data_device_manager_get_data_device(self->wayland.clipboard_manager.wl, wl_seat);
}
device_ctx->ll = self;
device_ctx->seat = wl_seat;
device_ctx->capabilities = capabilities;
device_ctx->device =
zwp_primary_selection_device_manager_v1_get_device(primary_selection->manager, wl_seat);
if(self->wayland.supports_zwp) {
zwp_primary_selection_device_v1_add_listener(device_ctx->device.zwp, &zwp_primary_selection_device_v1_listener, device_ctx);
} else {
wl_data_device_add_listener(device_ctx->device.wl, &wl_data_device_listener, device_ctx);
}
zwp_primary_selection_device_v1_add_listener(device_ctx->device, &primary_selection->listener, device_ctx);
device_ctx->offer = NULL;
arrpush(primary_selection->devices, device_ctx);
arrpush(self->wayland.clipboard_devices, device_ctx);
}
};
@@ -466,7 +745,6 @@ static wayland_protocol_t* wl_output_setup(MwU32 name, MwLL ll) {
}
static void wl_output_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
// wl_output_destroy(wayland->output);
}
/* wl_compositor setup function */
@@ -477,7 +755,6 @@ static wayland_protocol_t* wl_compositor_setup(MwU32 name, struct _MwLLWayland*
}
static void wl_compositor_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
// wl_compositor_destroy(wayland->compositor);
}
/* wl_subcompositor setup function */
@@ -544,6 +821,11 @@ static void xdg_toplevel_configure(void* data,
MwLL self = data;
int i;
/* Yes, somehow this can get called before */
if(!self->wayland.configured) {
return;
}
if(width == 0 || height == 0) {
width = self->wayland.ww;
height = self->wayland.wh;
@@ -565,6 +847,8 @@ static void xdg_toplevel_configure(void* data,
MwLLDispatch(self, resize, NULL);
MwLLDispatch(self, draw, NULL);
MwLLForceRender(self);
/*if(!self->wayland.egl_setup) {
self->wayland.egl_setup = egl_setup(self, self->wayland.x, self->wayland.y, width, height);
} else {
@@ -612,7 +896,6 @@ static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland
}
static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
// buffer_destroy(&wayland->framebuffer);
}
static void update_buffer(struct _MwLLWaylandShmBuffer* buffer) {
@@ -674,7 +957,8 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) {
memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size);
update_buffer(&wayland->framebuffer);
wayland->events_pending = MwTRUE;
wayland->events_pending += 1;
};
static void framebuffer_destroy(struct _MwLLWayland* wayland) {
buffer_destroy(&wayland->framebuffer);
@@ -711,25 +995,6 @@ static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland*
xdg_toplevel_icon_manager_v1_destroy(data->context);
}
/* Flush Wayland events */
static void wl_flush(MwLL handle) {
struct pollfd pfd;
int rc;
pfd.fd = wl_display_get_fd(handle->wayland.display);
pfd.events = POLLIN;
while(MwTRUE) {
rc = wl_display_flush(handle->wayland.display);
if(errno != EAGAIN || rc != -1) {
break;
}
if(poll(&pfd, 1, -1) == -1) {
break;
}
}
}
/* Standard Wayland event loop. */
static int event_loop(MwLL handle) {
struct pollfd fd;
@@ -803,6 +1068,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) {
WL_INTERFACE(wl_compositor);
WL_INTERFACE(wl_seat);
WL_INTERFACE(wl_output);
WL_INTERFACE(wl_data_device_manager);
WL_INTERFACE(zwp_primary_selection_device_manager_v1);
if(wayland->type == MWLL_WAYLAND_TOPLEVEL) {
WL_INTERFACE(xdg_wm_base);
@@ -869,6 +1135,8 @@ static void setup_toplevel(MwLL r, int x, int y) {
/* Perform the initial commit and wait for the first configure event */
wl_surface_commit(r->wayland.framebuffer.surface);
event_loop(r);
while(!r->wayland.configured) {
}
/* setup decorations if we can */
if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) {
@@ -893,6 +1161,8 @@ static void destroy_toplevel(MwLL r) {
zxdg_decoration_manager_v1_destroy(dec->manager);
}
wl_surface_destroy(r->wayland.framebuffer.surface);
wl_compositor_destroy(r->wayland.compositor);
xdg_surface_destroy(r->wayland.toplevel->xdg_surface);
@@ -924,12 +1194,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
r->wayland.display = parent->wayland.display;
r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor);
setup_callbacks(&r->wayland);
// printf("position %d %d\n", x, y);
r->wayland.registry = wl_display_get_registry(parent->wayland.display);
r->wayland.display = parent->wayland.display;
@@ -940,6 +1206,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
return;
}
r->wayland.framebuffer.surface = wl_compositor_create_surface(compositor);
r->wayland.sublevel->subsurface = wl_subcompositor_get_subsurface(r->wayland.sublevel->subcompositor, r->wayland.framebuffer.surface, parent_surface);
wl_subsurface_set_position(r->wayland.sublevel->subsurface, x, y);
@@ -985,11 +1253,14 @@ static void setup_popup(MwLL r) {
struct xdg_surface* xdg_surface;
MwLL topmost_parent = r->wayland.parent;
r->wayland.type = MWLL_WAYLAND_POPUP;
while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
topmost_parent = topmost_parent->wayland.parent;
}
r->wayland.type = MWLL_WAYLAND_POPUP;
r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup));
memset(r->wayland.popup, 0, sizeof(struct _MwLLWaylandPopup));
setup_callbacks(&r->wayland);
@@ -1002,11 +1273,6 @@ static void setup_popup(MwLL r) {
return;
}
r->wayland.popup = calloc(sizeof(struct _MwLLWaylandPopup), 0);
// r->wayland.popup->parent = parent;
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor);
r->wayland.popup->xdg_wm_base = WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context;
r->wayland.popup->xdg_positioner = xdg_wm_base_create_positioner(r->wayland.popup->xdg_wm_base);
@@ -1020,6 +1286,8 @@ static void setup_popup(MwLL r) {
xdg_surface = topmost_parent->wayland.toplevel->xdg_surface;
r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor);
r->wayland.popup->xdg_surface =
xdg_wm_base_get_xdg_surface(r->wayland.popup->xdg_wm_base, r->wayland.framebuffer.surface);
@@ -1038,6 +1306,7 @@ static void setup_popup(MwLL r) {
wl_surface_commit(r->wayland.framebuffer.surface);
event_loop(r);
}
/* Popup destroy function */
static void destroy_popup(MwLL r) {
xdg_popup_destroy(r->wayland.popup->xdg_popup);
@@ -1048,8 +1317,6 @@ static void destroy_popup(MwLL r) {
wl_surface_destroy(r->wayland.framebuffer.surface);
// free(r->wayland.popup);
wl_registry_destroy(r->wayland.registry);
}
@@ -1095,23 +1362,24 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
static void MwLLDestroyImpl(MwLL handle) {
int i;
struct timeval tv;
int select_ret;
event_loop(handle);
pthread_mutex_lock(&handle->wayland.eventsMutex);
MwLLDestroyCommon(handle);
buffer_destroy(&handle->wayland.framebuffer);
event_loop(handle);
framebuffer_destroy(&handle->wayland);
buffer_destroy(&handle->wayland.cursor);
wl_region_destroy(handle->wayland.region);
if(WAYLAND_GET_INTERFACE(handle->wayland, zwp_primary_selection_device_manager_v1) != NULL) {
primary_selection_context_t* primary_selection = WAYLAND_GET_INTERFACE(handle->wayland, zwp_primary_selection_device_manager_v1)->context;
for(i = 0; i < arrlen(primary_selection->devices); i++) {
zwp_primary_selection_offer_v1_destroy(primary_selection->devices[i]->offer);
if(handle->wayland.supports_zwp) {
zwp_primary_selection_source_v1_destroy(handle->wayland.clipboard_source.zwp);
} else {
wl_data_source_destroy(handle->wayland.clipboard_source.wl);
}
}
if(handle->wayland.icon != NULL) {
buffer_destroy(handle->wayland.icon);
wl_surface_destroy(handle->wayland.icon->surface);
@@ -1129,6 +1397,7 @@ static void MwLLDestroyImpl(MwLL handle) {
void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key);
handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx);
shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value);
}
shfree(handle->wayland.wl_protocol_map);
shfree(handle->wayland.wl_protocol_setup_map);
@@ -1140,6 +1409,16 @@ static void MwLLDestroyImpl(MwLL handle) {
wl_keyboard_destroy(handle->wayland.keyboard);
}
/* sleep long enough that any active attempts to wait for the mutex will have given up and we can safely unlock/destroy it */
tv.tv_sec = 0;
tv.tv_usec = 250;
do {
select_ret = select(1, NULL, NULL, NULL, &tv);
} while((select_ret == -1) && (errno == EINTR));
pthread_mutex_unlock(&handle->wayland.eventsMutex);
pthread_mutex_destroy(&handle->wayland.eventsMutex);
free(handle);
}
@@ -1151,7 +1430,7 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign
}
static void MwLLSetXYImpl(MwLL handle, int x, int y) {
if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) {
if(handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) {
region_invalidate(handle);
handle->wayland.x = x;
handle->wayland.y = y;
@@ -1164,6 +1443,7 @@ static void MwLLSetXYImpl(MwLL handle, int x, int y) {
static void MwLLSetWHImpl(MwLL handle, int w, int h) {
region_invalidate(handle);
/* Prevent an integer underflow when the w/h is too low */
if((w < 10 || h < 10)) {
handle->wayland.ww = 10;
@@ -1173,7 +1453,7 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) {
handle->wayland.ww = w;
handle->wayland.wh = h;
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL && handle->wayland.configured) {
xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
}
@@ -1200,7 +1480,8 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL
}
cairo_close_path(handle->wayland.cairo);
cairo_fill(handle->wayland.cairo);
handle->wayland.events_pending = MwTRUE;
handle->wayland.events_pending += 1;
}
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
@@ -1218,7 +1499,8 @@ static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
}
cairo_close_path(handle->wayland.cairo);
cairo_stroke(handle->wayland.cairo);
handle->wayland.events_pending = MwTRUE;
handle->wayland.events_pending += 1;
}
static void MwLLBeginDrawImpl(MwLL handle) {
@@ -1226,7 +1508,8 @@ static void MwLLBeginDrawImpl(MwLL handle) {
static void MwLLEndDrawImpl(MwLL handle) {
update_buffer(&handle->wayland.framebuffer);
handle->wayland.events_pending = MwTRUE;
handle->wayland.events_pending += 1;
}
static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) {
@@ -1250,13 +1533,29 @@ static void MwLLFreeColorImpl(MwLLColor color) {
}
static int MwLLPendingImpl(MwLL handle) {
return handle->wayland.events_pending || wl_display_dispatch(handle->wayland.display);
MwBool pending = MwFALSE;
struct timespec timeout;
int i;
if(handle->wayland.always_render) {
return event_loop(handle);
}
timeout.tv_nsec = 10;
timeout.tv_sec = 0;
return handle->wayland.force_render || handle->wayland.events_pending || wl_display_dispatch_timeout(handle->wayland.display, &timeout);
}
static void MwLLNextEventImpl(MwLL handle) {
if(!handle->wayland.always_render) {
event_loop(handle);
}
if(handle->wayland.events_pending) {
handle->wayland.events_pending = MwFALSE;
handle->wayland.events_pending = 0;
}
if(handle->wayland.force_render) {
handle->wayland.force_render = 0;
}
}
@@ -1336,7 +1635,8 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
int i = 0;
if(handle->wayland.icon == NULL) {
handle->wayland.icon = calloc(sizeof(struct _MwLLWaylandShmBuffer), 0);
handle->wayland.icon = malloc(sizeof(struct _MwLLWaylandShmBuffer));
memset(handle->wayland.icon, 0, sizeof(struct _MwLLWaylandShmBuffer));
handle->wayland.icon->shm = handle->wayland.framebuffer.shm;
}
@@ -1367,6 +1667,8 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
static void MwLLForceRenderImpl(MwLL handle) {
wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
handle->wayland.force_render = MwTRUE;
/*
if(handle->wayland.egl_setup) {
timed_redraw_by_epoch(handle, 25);
@@ -1485,59 +1787,28 @@ static void MwLLGrabPointerImpl(MwLL handle, int toggle) {
}
static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
if(handle->wayland.clipboard_buffer != NULL) {
free(handle->wayland.clipboard_buffer);
}
handle->wayland.clipboard_buffer = malloc(strlen(text));
strcpy(handle->wayland.clipboard_buffer, text);
if(handle->wayland.supports_zwp) {
for(int i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) {
wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i];
zwp_primary_selection_device_v1_set_selection(device->device.zwp, handle->wayland.clipboard_source.zwp, handle->wayland.keyboard_serial);
}
} else {
for(int i = 0; i < arrlen(handle->wayland.clipboard_devices); i++) {
wl_clipboard_device_context_t* device = handle->wayland.clipboard_devices[i];
wl_data_device_set_selection(device->device.wl, handle->wayland.clipboard_source.wl, handle->wayland.keyboard_serial);
}
}
}
static char* MwLLGetClipboardImpl(MwLL handle) {
if(WAYLAND_GET_INTERFACE(handle->wayland, zwp_primary_selection_device_manager_v1) != NULL) {
primary_selection_context_t* primary_selection = WAYLAND_GET_INTERFACE(handle->wayland, zwp_primary_selection_device_manager_v1)->context;
int i, n = 0;
int fds[2];
struct timeval timeout;
fd_set set;
char* clip_buffer = NULL;
if(pipe(fds) != 0) {
return NULL;
}
FD_ZERO(&set);
FD_SET(fds[0], &set);
timeout.tv_sec = 0;
timeout.tv_usec = 100;
for(i = 0; i < arrlen(primary_selection->devices); i++) {
primary_selection_device_context_t* device = primary_selection->devices[i];
size_t size = 0;
char ch;
int rc = 0;
zwp_primary_selection_offer_v1_receive(device->offer, "text/plain", fds[1]);
wl_flush(handle);
fcntl(fds[0], F_SETFL, O_NONBLOCK);
while(MwTRUE) {
rc = select(fds[0] + 1, &set, NULL, NULL, &timeout);
if(rc <= 0) {
break;
} else {
read(fds[0], &ch, 1);
arrpush(clip_buffer, ch);
if(n++ >= 10240) {
break;
}
}
}
return clip_buffer;
}
// zwp_primary_selection_source_v1_send();
// arrpush(primary_selection->devices, device);
}
return NULL;
static void MwLLGetClipboardImpl(MwLL handle) {
/* no-op */
return;
}
static void MwLLMakeToolWindowImpl(MwLL handle) {

View File

@@ -211,6 +211,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
r->x11.colormap = DefaultColormap(r->x11.display, XDefaultScreen(r->x11.display));
r->x11.wm_delete = XInternAtom(r->x11.display, "WM_DELETE_WINDOW", False);
r->x11.wm_protocols = XInternAtom(r->x11.display, "WM_PROTOCOLS", False);
XSetWMProtocols(r->x11.display, r->x11.window, &r->x11.wm_delete, 1);
r->x11.gc = XCreateGC(r->x11.display, r->x11.window, 0, NULL);
@@ -471,7 +472,7 @@ static void MwLLNextEventImpl(MwLL handle) {
handle->x11.width = ev.xconfigure.width;
handle->x11.height = ev.xconfigure.height;
} else if(ev.type == ClientMessage) {
if(ev.xclient.data.l[0] == (long)handle->x11.wm_delete) {
if(ev.xclient.message_type == handle->x11.wm_protocols && ev.xclient.data.l[0] == (long)handle->x11.wm_delete) {
MwLLDispatch(handle, close, NULL);
}
} else if(ev.type == FocusIn) {
@@ -956,45 +957,10 @@ static void MwLLSetClipboardImpl(MwLL handle, const char* text) {
(void)text;
}
static char* MwLLGetClipboardImpl(MwLL handle) {
Atom clip, target, prop;
XEvent ev;
XEvent* queue = NULL;
char* r = NULL;
static void MwLLGetClipboardImpl(MwLL handle) {
/* TODO */
clip = XInternAtom(handle->x11.display, "CLIPBOARD", 0);
target = XA_STRING;
prop = XInternAtom(handle->x11.display, "XSEL_DATA", 0);
XConvertSelection(handle->x11.display, clip, target, prop, handle->x11.window, CurrentTime);
while(1) {
XNextEvent(handle->x11.display, &ev);
if(ev.type == SelectionNotify) {
if(ev.xselection.selection == clip && ev.xselection.property != 0) {
Atom t;
unsigned long size, N;
char* data;
int format;
XGetWindowProperty(ev.xselection.display, ev.xselection.requestor, ev.xselection.property, 0, (~0L), 0, AnyPropertyType, &t, &format, &size, &N, (unsigned char**)&data);
if(t == target) {
r = MwStringDuplicate(data);
XFree(data);
}
XDeleteProperty(ev.xselection.display, ev.xselection.requestor, ev.xselection.property);
}
break;
}
}
while(arrlen(queue) > 0) {
XPutBackEvent(handle->x11.display, &queue[0]);
arrdel(queue, 0);
}
arrfree(queue);
return r;
(void)handle;
}
static void MwLLMakeToolWindowImpl(MwLL handle) {

View File

@@ -107,6 +107,13 @@ static void llfocusouthandler(MwLL handle, void* data) {
MwDispatchUserHandler(h, MwNfocusOutHandler, data);
}
static void llclipboardhandler(MwLL handle, void* data) {
MwWidget h = (MwWidget)handle->common.user;
MwDispatch3(h, clipboard, data);
MwDispatchUserHandler(h, MwNclipboardHandler, data);
}
MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, int x, int y, unsigned int width, unsigned int height) {
MwWidget h = malloc(sizeof(*h));
@@ -148,6 +155,7 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent,
h->lowlevel->common.handler->key_released = llkeyrelhandler;
h->lowlevel->common.handler->focus_in = llfocusinhandler;
h->lowlevel->common.handler->focus_out = llfocusouthandler;
h->lowlevel->common.handler->clipboard = llclipboardhandler;
}
if(parent != NULL) arrput(parent->children, h);
@@ -261,6 +269,8 @@ void MwDestroyWidget(MwWidget handle) {
if(i == arrlen(handle->parent->destroy_queue)) {
arrput(handle->parent->destroy_queue, handle);
}
MwDispatch(handle->parent, children_update);
}
destroy_children(handle);
handle->destroyed = 1;
@@ -385,6 +395,9 @@ void MwSetInteger(MwWidget handle, const char* key, int n) {
MwDispatch3(handle, prop_change, key);
if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key);
}
if(strcmp(key, MwNforceInverted) == 0) {
MwForceRender(handle);
}
}
void MwSetText(MwWidget handle, const char* key, const char* value) {

View File

@@ -10,6 +10,8 @@ const char* MwDefaultDarkForeground = "#ddd";
const char* MwDefaultDarkSubBackground = "#333";
const char* MwDefaultDarkSubForeground = "#ddd";
const int MwDefaultShadow = -32;
int MwDefaultBorderWidth(MwWidget handle) {
int bw = MwGetInteger(handle, MwNborderWidth);

View File

@@ -1,6 +1,7 @@
#include <Mw/Milsko.h>
#ifdef USE_STB_IMAGE
#ifdef NO_IMAGE
#elif defined(USE_STB_IMAGE)
#include "../external/stb_image.h"
#else
#include <png.h>
@@ -130,6 +131,9 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) {
}
void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) {
int inv;
if((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv) invert = 1;
if(MwGetInteger(handle, MwNmodernLook)) {
MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0);
} else {
@@ -502,7 +506,8 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert,
MwLLFreeColor(darker);
}
#ifndef USE_STB_IMAGE
#if defined(NO_IMAGE)
#elif !defined(USE_STB_IMAGE)
static void PNGCAPI user_error(png_structp png, const char* str) {
(void)str;
@@ -617,7 +622,9 @@ static unsigned char* load_jpeg(FILE* f, int* w, int* h) {
#endif
static unsigned char* load_image(const char* path, int* w, int* h) {
#ifdef USE_STB_IMAGE
#if defined(NO_IMAGE)
return NULL;
#elif defined(USE_STB_IMAGE)
int ch;
return stbi_load(path, w, h, &ch, 4);

View File

@@ -46,7 +46,7 @@ void (*MwLLFocus)(MwLL handle);
void (*MwLLGrabPointer)(MwLL handle, int toggle);
void (*MwLLSetClipboard)(MwLL handle, const char* text);
char* (*MwLLGetClipboard)(MwLL handle);
void (*MwLLGetClipboard)(MwLL handle);
void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point);
void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect);

View File

@@ -47,6 +47,8 @@ static void layout(MwWidget handle) {
int s = MwGetInteger(handle->children[i], MwNfixedSize);
if(n == MwDEFAULT) n = 1;
if(handle->children[i]->destroyed) continue;
if(s != MwDEFAULT) {
sz -= s + Margin;
} else {
@@ -60,6 +62,8 @@ static void layout(MwWidget handle) {
int wsz;
if(n == MwDEFAULT) n = 1;
if(handle->children[i]->destroyed) continue;
if(s != MwDEFAULT) {
wsz = s;
} else {
@@ -110,7 +114,7 @@ MwClassRec MwBoxClassRec = {
resize, /* resize */
children_update, /* children_update */
children_prop_change, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -20,6 +20,7 @@ static void draw(MwWidget handle) {
const char* str = MwGetText(handle, MwNtext);
MwLLPixmap px = MwGetVoid(handle, MwNpixmap);
MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap);
int inv;
if(str == NULL) str = "";
@@ -29,7 +30,7 @@ static void draw(MwWidget handle) {
r.height = MwGetInteger(handle, MwNheight);
if(MwGetInteger(handle, MwNflat)) {
if(handle->pressed) {
if(handle->pressed || ((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv)) {
MwDrawWidgetBack(handle, &r, base, handle->pressed, 1);
} else {
MwDrawRect(handle, &r, base);
@@ -38,7 +39,7 @@ static void draw(MwWidget handle) {
MwDrawWidgetBack(handle, &r, base, handle->pressed, 1);
}
if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx);
if(MwGetInteger(handle, MwNflat) && !handle->pressed) {
if(MwGetInteger(handle, MwNflat) && !(handle->pressed || ((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv))) {
r.x += MwDefaultBorderWidth(handle);
r.y += MwDefaultBorderWidth(handle);
r.width -= MwDefaultBorderWidth(handle) * 2;
@@ -106,7 +107,7 @@ MwClassRec MwButtonClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -53,7 +53,7 @@ MwClassRec MwCheckBoxClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -204,7 +204,7 @@ MwClassRec MwComboBoxClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -109,20 +109,7 @@ static void key(MwWidget handle, int code) {
} else if(code == MwLLKeyEnter) {
MwDispatchUserHandler(handle, MwNactivateHandler, NULL);
} else if(code == (MwLLControlMask | 'v')) {
char* c = MwLLGetClipboard(handle->lowlevel);
if(c != NULL) {
char* out = malloc(strlen(str) + strlen(c) + 1);
MwUTF8Copy(str, 0, out, 0, t->cursor);
MwUTF8Copy(c, 0, out, t->cursor, MwUTF8Length(c));
MwUTF8Copy(str, t->cursor, out, t->cursor + MwUTF8Length(c), MwUTF8Length(str) - t->cursor);
t->cursor += MwUTF8Length(c);
MwSetText(handle, MwNtext, out);
free(out);
free(c);
}
MwLLGetClipboard(handle->lowlevel);
} else if(!(code & MwLLKeyMask)) {
int incr = 0;
out = malloc(strlen(str) + 5 + 1);
@@ -157,6 +144,23 @@ static void prop_change(MwWidget handle, const char* prop) {
}
}
static void clipboard(MwWidget handle, const char* data) {
MwEntry t = handle->internal;
const char* str = MwGetText(handle, MwNtext);
char* out = malloc(strlen(str) + strlen(data) + 1);
if(str == NULL) str = "";
MwUTF8Copy(str, 0, out, 0, t->cursor);
MwUTF8Copy(data, 0, out, t->cursor, MwUTF8Length(data));
MwUTF8Copy(str, t->cursor, out, t->cursor + MwUTF8Length(data), MwUTF8Length(str) - t->cursor);
t->cursor += MwUTF8Length(data);
MwSetText(handle, MwNtext, out);
free(out);
}
MwClassRec MwEntryClassRec = {
create, /* create */
destroy, /* destroy */
@@ -173,7 +177,7 @@ MwClassRec MwEntryClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
clipboard, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -61,7 +61,7 @@ MwClassRec MwFrameClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -57,7 +57,7 @@ MwClassRec MwImageClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -15,6 +15,7 @@ static int create(MwWidget handle) {
MwSetInteger(handle, MwNbold, 0);
MwSetInteger(handle, MwNsevenSegment, 0);
MwSetInteger(handle, MwNlength, 4);
MwSetInteger(handle, MwNleftPadding, 0);
return 0;
}
@@ -126,7 +127,7 @@ static void draw(MwWidget handle) {
MwPoint p;
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground));
MwLLColor shadow = MwLightenColor(handle, base, -32, -32, -32);
MwLLColor shadow = MwLightenColor(handle, base, MwDefaultShadow, MwDefaultShadow, MwDefaultShadow);
int align;
const char* str = MwGetText(handle, MwNtext);
MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap);
@@ -253,10 +254,11 @@ static void draw(MwWidget handle) {
for(j = 1; j >= 0; j--) {
MwLLColor cl = j == 1 ? shadow : text;
for(cy = 1; cy < h - 1; cy++) {
int c = (l_one - s_one) / 2 + s_one;
int h = s_one / 2;
int c = (l_one - h) / 2 + s_one;
int c1 = (c <= cy && cy <= (c + s_one)) ? 1 : 0;
int c2 = ((s_one + l_one + c) <= cy && cy <= (s_one + l_one + c + s_one)) ? 1 : 0;
int c1 = (c <= cy && cy <= (c + h)) ? 1 : 0;
int c2 = ((s_one + l_one + c) <= cy && cy <= (s_one + l_one + c + h)) ? 1 : 0;
if(c1 || c2) {
for(cx = x; cx < x + s_one; cx++) {
@@ -309,6 +311,8 @@ static void draw(MwWidget handle) {
MwLLDestroyPixmap(px);
} else {
r.width -= MwGetInteger(handle, MwNleftPadding);
if(align == MwALIGNMENT_CENTER) {
p.x = r.width / 2;
} else if(align == MwALIGNMENT_BEGINNING) {
@@ -317,6 +321,15 @@ static void draw(MwWidget handle) {
p.x = r.width - MwTextWidth(handle, str) / 2;
}
p.y = r.height / 2;
p.x += MwGetInteger(handle, MwNleftPadding);
p.x += 1;
p.y += 1;
MwDrawText(handle, &p, str, MwGetInteger(handle, MwNbold), MwALIGNMENT_CENTER, shadow);
p.x -= 1;
p.y -= 1;
MwDrawText(handle, &p, str, MwGetInteger(handle, MwNbold), MwALIGNMENT_CENTER, text);
}
@@ -326,7 +339,7 @@ static void draw(MwWidget handle) {
}
static void prop_change(MwWidget handle, const char* key) {
if(strcmp(key, MwNtext) == 0 || strcmp(key, MwNalignment) == 0 || strcmp(key, MwNsevenSegment) == 0) MwForceRender(handle);
if(strcmp(key, MwNtext) == 0 || strcmp(key, MwNalignment) == 0 || strcmp(key, MwNsevenSegment) == 0 || strcmp(key, MwNlength) == 0 || strcmp(key, MwNleftPadding) == 0) MwForceRender(handle);
}
static void mwLabelSetSevenSegmentImpl(MwWidget handle, int index, unsigned char data) {
@@ -362,7 +375,7 @@ MwClassRec MwLabelClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -608,7 +608,7 @@ MwClassRec MwListBoxClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -204,7 +204,7 @@ MwClassRec MwMenuClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -143,7 +143,7 @@ MwClassRec MwNumberEntryClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -42,6 +42,19 @@ typedef struct x11opengl {
} x11opengl_t;
#endif
#ifdef USE_WAYLAND
#include <EGL/egl.h>
#include <wayland-egl-core.h>
typedef struct waylandopengl {
EGLNativeWindowType egl_window_native;
EGLDisplay egl_display;
EGLContext egl_context;
EGLSurface egl_surface;
EGLConfig egl_config;
} waylandopengl_t;
#endif
static int create(MwWidget handle) {
void* r = NULL;
#ifdef USE_GDI
@@ -105,7 +118,90 @@ static int create(MwWidget handle) {
#endif
#ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) {
/* todo */
int err;
EGLint numConfigs;
EGLint majorVersion;
EGLint minorVersion;
EGLContext context;
EGLSurface surface;
EGLint fbAttribs[] =
{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE};
EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 1,
EGL_CONTEXT_MAJOR_VERSION, 1,
EGL_CONTEXT_MINOR_VERSION, 1,
EGL_NONE};
EGLDisplay display;
waylandopengl_t* o = r = malloc(sizeof(*o));
MwLL topmost_parent = handle->lowlevel->wayland.parent;
topmost_parent->wayland.always_render = MwTRUE;
while(topmost_parent->wayland.parent != NULL) {
topmost_parent = topmost_parent->wayland.parent;
topmost_parent->wayland.always_render = MwTRUE;
}
display = eglGetDisplay((EGLNativeDisplayType)handle->lowlevel->wayland.display);
if(display == EGL_NO_DISPLAY) {
printf("ERROR: eglGetDisplay, %0X\n", eglGetError());
return MwFALSE;
}
/* Initialize EGL */
if(!eglInitialize(display, &majorVersion, &minorVersion)) {
printf("ERROR: eglInitialize, %0X\n", eglGetError());
return MwFALSE;
}
/* Get configs */
if((eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) {
printf("ERROR: eglGetConfigs, %0X\n", eglGetError());
return MwFALSE;
}
/* Choose config */
if((eglChooseConfig(display, fbAttribs, &o->egl_config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) {
printf("ERROR: eglChooseConfig, %0X\n", eglGetError());
return MwFALSE;
}
o->egl_window_native =
(EGLNativeWindowType)wl_egl_window_create(handle->lowlevel->wayland.framebuffer.surface, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh);
if(o->egl_window_native == EGL_NO_SURFACE) {
printf("ERROR: wl_egl_window_create, EGL_NO_SURFACE\n");
return MwFALSE;
}
/* Create a surface */
surface = eglCreateWindowSurface(display, o->egl_config, o->egl_window_native, NULL);
if(surface == EGL_NO_SURFACE) {
printf("ERROR: eglCreateWindowSurface, %0X\n", eglGetError());
return MwFALSE;
}
eglBindAPI(EGL_OPENGL_API);
/* Create a GL context */
context = eglCreateContext(display, o->egl_config, EGL_NO_CONTEXT, contextAttribs);
if(context == EGL_NO_CONTEXT) {
printf("ERROR: eglCreateContext, %0X\n", eglGetError());
return MwFALSE;
}
if(!eglMakeCurrent(display, surface, surface, context)) {
printf("ERROR: eglMakeCurrent (setup): %0X\n", eglGetError());
}
o->egl_display = display;
o->egl_surface = surface;
o->egl_context = context;
}
#endif
@@ -165,7 +261,11 @@ static void mwOpenGLMakeCurrentImpl(MwWidget handle) {
#endif
#ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) {
/* todo */
waylandopengl_t* o = handle->internal;
if(!eglMakeCurrent(o->egl_display, o->egl_surface, o->egl_surface, o->egl_context)) {
printf("ERROR: eglMakeCurrent, %0X\n", eglGetError());
}
}
#endif
}
@@ -187,7 +287,13 @@ static void mwOpenGLSwapBufferImpl(MwWidget handle) {
#endif
#ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) {
/* todo */
waylandopengl_t* o = handle->internal;
eglSwapInterval(o->egl_display, 0);
if(!eglSwapBuffers(o->egl_display, o->egl_surface)) {
printf("ERROR: eglSwapBuffers, %0X\n", eglGetError());
};
wl_egl_window_resize((struct wl_egl_window*)o->egl_window_native, handle->lowlevel->wayland.ww, handle->lowlevel->wayland.wh, 0, 0);
MwLLForceRender(handle->lowlevel);
}
#endif
}
@@ -209,7 +315,7 @@ static void* mwOpenGLGetProcAddressImpl(MwWidget handle, const char* name) {
#endif
#ifdef USE_WAYLAND
if(handle->lowlevel->common.type == MwLLBackendWayland) {
/* todo */
return eglGetProcAddress(name);
}
#endif
return NULL;
@@ -244,7 +350,7 @@ MwClassRec MwOpenGLClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -61,7 +61,7 @@ MwClassRec MwProgressBarClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -62,7 +62,7 @@ MwClassRec MwRadioBoxClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -272,7 +272,7 @@ MwClassRec MwScrollBarClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -50,7 +50,7 @@ MwClassRec MwSeparatorClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -6,6 +6,7 @@ static int create(MwWidget handle) {
MwLLBeginStateChange(handle->lowlevel);
MwSetDefault(handle);
MwSetInteger(handle, MwNleftPadding, 0);
return 0;
}
@@ -53,25 +54,27 @@ static void draw(MwWidget handle) {
rc.x = MwDefaultBorderWidth(handle) * 2;
rc.y = p.y;
rc.width = r.width - (rc.x * 2);
rc.height = MwDefaultBorderWidth(handle) * 2;
rc.width = r.width - (rc.x * 2) - MwGetInteger(handle, MwNleftPadding);
rc.height = 2;
MwDrawFrame(handle, &rc, base, 1);
rc.x += MwGetInteger(handle, MwNleftPadding);
p.y += MwDefaultBorderWidth(handle) * 2 + 1;
MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0);
p.y += 2 + 1;
} else {
int tw = MwTextWidth(handle, menu->sub[i]->name);
int th = MwTextHeight(handle, menu->sub[i]->name);
if(menu->sub[i]->wsub != NULL) {
r.x = 0;
r.x = MwGetInteger(handle, MwNleftPadding);
r.y = p.y - 3;
r.width = tw + 15 + 5 * 2;
r.width = MwGetInteger(handle, MwNwidth) - MwGetInteger(handle, MwNleftPadding);
r.height = th + 3 * 2;
MwDrawWidgetBack(handle, &r, base, 0, MwTRUE);
}
p.x = 5 + tw / 2;
p.x = 5 + tw / 2 + MwGetInteger(handle, MwNleftPadding);
p.y += th / 2;
MwDrawText(handle, &p, menu->sub[i]->name, menu->sub[i]->wsub != NULL ? 1 : 0, MwALIGNMENT_CENTER, text);
@@ -79,7 +82,7 @@ static void draw(MwWidget handle) {
if(arrlen(menu->sub[i]->sub) > 0) {
MwRect tr;
tr.x = p.x + tw / 2 + 5;
tr.x = MwGetInteger(handle, MwNwidth) - MwDefaultBorderWidth(handle) - 11 - 2;
tr.y = p.y - th / 2 + 2;
tr.width = tr.height = 11;
@@ -116,7 +119,11 @@ static void click(MwWidget handle) {
int th = MwTextHeight(handle, menu->sub[i]->name);
rc.height = th;
if(rc.x <= handle->mouse_point.x && rc.y <= handle->mouse_point.y && handle->mouse_point.x <= (int)(rc.x + rc.width) && handle->mouse_point.y <= (int)(rc.y + rc.height)) {
if(strcmp(menu->sub[i]->name, "----") == 0) {
rc.height = 2 - 1;
}
if(MwGetInteger(handle, MwNleftPadding) <= handle->mouse_point.x && rc.y <= handle->mouse_point.y && handle->mouse_point.y <= (int)(rc.y + rc.height)) {
if(menu->sub[i]->wsub == NULL && arrlen(menu->sub[i]->sub) > 0) {
MwPoint p;
int j;
@@ -126,14 +133,14 @@ static void click(MwWidget handle) {
menu->sub[j]->wsub = NULL;
}
p.x = rc.x + rc.width + 3;
p.x = MwGetInteger(handle, MwNwidth);
p.y = rc.y - 3;
menu->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0);
MwSubMenuAppear(menu->sub[i]->wsub, menu->sub[i], &p, 0);
i = -1;
} else if(menu->sub[i]->wsub != NULL && arrlen(menu->sub[i]->sub) > 0) {
while(w->parent->widget_class != MwMenuClass) w = w->parent;
while(w->parent->widget_class == MwSubMenuClass) w = w->parent;
MwDestroyWidget(menu->sub[i]->wsub);
menu->sub[i]->wsub = NULL;
@@ -142,7 +149,7 @@ static void click(MwWidget handle) {
MwForceRender(handle);
} else if(strcmp(menu->sub[i]->name, "----") != 0 && arrlen(menu->sub[i]->sub) == 0) {
while(w->parent->widget_class != MwMenuClass) w = w->parent;
while(w->parent->widget_class == MwSubMenuClass) w = w->parent;
MwGetBeforeStep(w, &jmp);
MwDestroyWidget(w);
@@ -160,49 +167,61 @@ static void click(MwWidget handle) {
}
static void mwSubMenuAppearImpl(MwWidget handle, MwMenu menu, MwPoint* point, int diff_calc) {
int i, w = 0, h = 0;
MwRect rc;
MwRect rc, sz;
MwPoint p = *point;
MwSubMenuGetSize(handle, menu, &sz);
MwGetScreenSize(handle, &rc);
handle->internal = menu;
for(i = 0; i < arrlen(menu->sub); i++) {
if(strcmp(menu->sub[i]->name, "----") == 0) {
h += MwDefaultBorderWidth(handle) * 2 + 2;
} else {
int tw = MwTextWidth(handle, menu->sub[i]->name);
h += MwTextHeight(handle, menu->sub[i]->name) + 3;
if(tw > w) {
w = tw;
}
}
}
w += 10 + 15;
h += 3;
if(diff_calc) {
p.y = rc.height - p.y - h;
p.y = p.y - sz.height;
}
MwLLMakeToolWindow(handle->lowlevel);
MwLLDetach(handle->lowlevel, &p);
if(MwGetInteger(handle, MwNy) + h > rc.height) {
if(MwGetInteger(handle, MwNy) + sz.height > rc.height) {
MwVaApply(handle,
MwNy, rc.height - h,
MwNy, rc.height - sz.height,
NULL);
}
MwLLEndStateChange(handle->lowlevel);
MwVaApply(handle,
MwNwidth, w,
MwNheight, h,
MwNwidth, sz.width,
MwNheight, sz.height,
NULL);
}
static void mwSubMenuGetSizeImpl(MwWidget handle, MwMenu menu, MwRect* rect) {
int i;
rect->width = 0;
rect->height = 0;
for(i = 0; i < arrlen(menu->sub); i++) {
if(strcmp(menu->sub[i]->name, "----") == 0) {
rect->height += 2 + 2;
} else {
int tw = MwTextWidth(handle, menu->sub[i]->name);
rect->height += MwTextHeight(handle, menu->sub[i]->name) + 3;
if(tw > rect->width) {
rect->width = tw;
}
}
}
rect->width += MwGetInteger(handle, MwNleftPadding);
rect->width += 10 + 15;
rect->height += 3;
rect->width += 16;
}
static void func_handler(MwWidget handle, const char* name, void* out, va_list va) {
(void)out;
@@ -211,6 +230,10 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v
MwPoint* point = va_arg(va, MwPoint*);
int diff_calc = va_arg(va, int);
mwSubMenuAppearImpl(handle, menu, point, diff_calc);
} else if(strcmp(name, "mwSubMenuGetSize") == 0) {
MwMenu menu = va_arg(va, MwMenu);
MwRect* rect = va_arg(va, MwRect*);
mwSubMenuGetSizeImpl(handle, menu, rect);
}
}
@@ -230,7 +253,7 @@ MwClassRec MwSubMenuClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -496,7 +496,7 @@ MwClassRec MwTreeViewClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -191,7 +191,7 @@ MwClassRec MwViewportClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -524,7 +524,7 @@ MwClassRec MwVulkanClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

View File

@@ -59,7 +59,7 @@ MwClassRec MwWindowClassRec = {
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL, /* clipboard */
NULL,
NULL,
NULL,

105
tools/gendcl.pl Executable file
View File

@@ -0,0 +1,105 @@
#!/usr/bin/env perl
our $clean = 0;
my @objs = ();
sub compile {
my ($source) = @_;
my $object = "";
my $dir = "";
$dir = $source;
$dir =~ s/\/([^\/]+)$//;
$source =~ s/^(.+)\/([^\/]+)$/[\/\1]\2/;
$source =~ s/\//\./g;
$object = $source;
$object =~ s/\.c$/.obj/;
print(OUT "\$ if f\$search(\"$object;*\") .eqs. \"\"\n");
print(OUT "\$ then\n");
print(OUT "\$ write sys\$output \"CC $object\"\n");
print(OUT
"\$ cc /include_directory=(\"./include\",\"./$dir\") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=$object $source\n"
);
print(OUT "\$ endif\n");
push(@objs, $object);
}
sub clean {
my ($source) = @_;
my $object = "";
my $dir = "";
$source =~ s/^(.+)\/([^\/]+)$/[\/\1]\2/;
$source =~ s/\//\./g;
$object = $source;
$object =~ s/\.c$/.obj/;
print(OUT
"\$ if f\$search(\"$object\") .nes. \"\" then delete $object;*\n");
}
sub thing {
if ($clean) {
clean($_[0]);
}
else {
compile($_[0]);
}
}
sub scan {
my ($dir) = @_;
opendir(my $dh, $dir);
while (my $file = readdir($dh)) {
if ( !(($dir . "/" . $file) eq "src/widget/opengl.c")
&& !(($dir . "/" . $file) eq "src/widget/vulkan.c")
&& !(($dir . "/" . $file) eq "external/stb_truetype.c")
&& !(($dir . "/" . $file) eq "external/stb_image.c")
&& ($file =~ /\.c$/))
{
thing($dir . "/" . $file);
}
}
closedir($dh);
}
for (my $i = 0 ; $i < 2 ; $i++) {
$clean = $i;
open(OUT, ">", $i == 0 ? "vms/build.com" : "vms/clean.com");
scan("src");
scan("src/cursor");
scan("src/widget");
scan("src/dialog");
scan("src/font");
scan("src/icon");
scan("src/abstract");
scan("external");
thing("src/backend/x11.c");
if ($i == 0) {
print(OUT "\$ if f\$search(\"[.src]MwSHR.exe;*\") .eqs. \"\"\n");
print(OUT "\$ then\n");
print(OUT "\$ write sys\$output \"LINK [.src]MwSHR.exe\"\n");
print(OUT "\$ OPEN /WRITE LINK_OPT LINK.OPT\n");
foreach my $obj (@objs) {
print(OUT "\$ WRITE LINK_OPT \"$obj\"\n");
}
print(OUT "\$ WRITE LINK_OPT \"SYS\$LIBRARY:DECW\$XLIBSHR/SHARE\"\n");
print(OUT "\$ WRITE LINK_OPT \"SYS\$LIBRARY:DPML\$SHR/SHARE\"\n");
print(OUT "\$ CLOSE LINK_OPT\n");
print(OUT "\$ link /SHAREABLE=[.src]MwSHR.exe LINK.OPT/options\n");
print(OUT "\$ DELETE LINK.OPT;*\n");
print(OUT "\$ endif\n");
}
else {
clean("src/MwSHR.exe");
}
close(OUT);
}

382
vms/build.com Normal file
View File

@@ -0,0 +1,382 @@
$ if f$search("[.src]color.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]color.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]color.obj [.src]color.c
$ endif
$ if f$search("[.src]core.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]core.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]core.obj [.src]core.c
$ endif
$ if f$search("[.src]default.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]default.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]default.obj [.src]default.c
$ endif
$ if f$search("[.src]draw.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]draw.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]draw.obj [.src]draw.c
$ endif
$ if f$search("[.src]error.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]error.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]error.obj [.src]error.c
$ endif
$ if f$search("[.src]lowlevel.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]lowlevel.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]lowlevel.obj [.src]lowlevel.c
$ endif
$ if f$search("[.src]string.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]string.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]string.obj [.src]string.c
$ endif
$ if f$search("[.src]text.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]text.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]text.obj [.src]text.c
$ endif
$ if f$search("[.src]unicode.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src]unicode.obj"
$ cc /include_directory=("./include","./src") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src]unicode.obj [.src]unicode.c
$ endif
$ if f$search("[.src.cursor]arrow.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.cursor]arrow.obj"
$ cc /include_directory=("./include","./src/cursor") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.cursor]arrow.obj [.src.cursor]arrow.c
$ endif
$ if f$search("[.src.cursor]cross.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.cursor]cross.obj"
$ cc /include_directory=("./include","./src/cursor") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.cursor]cross.obj [.src.cursor]cross.c
$ endif
$ if f$search("[.src.cursor]default.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.cursor]default.obj"
$ cc /include_directory=("./include","./src/cursor") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.cursor]default.obj [.src.cursor]default.c
$ endif
$ if f$search("[.src.cursor]hidden.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.cursor]hidden.obj"
$ cc /include_directory=("./include","./src/cursor") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.cursor]hidden.obj [.src.cursor]hidden.c
$ endif
$ if f$search("[.src.cursor]text.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.cursor]text.obj"
$ cc /include_directory=("./include","./src/cursor") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.cursor]text.obj [.src.cursor]text.c
$ endif
$ if f$search("[.src.widget]button.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]button.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]button.obj [.src.widget]button.c
$ endif
$ if f$search("[.src.widget]checkbox.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]checkbox.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]checkbox.obj [.src.widget]checkbox.c
$ endif
$ if f$search("[.src.widget]combobox.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]combobox.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]combobox.obj [.src.widget]combobox.c
$ endif
$ if f$search("[.src.widget]entry.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]entry.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]entry.obj [.src.widget]entry.c
$ endif
$ if f$search("[.src.widget]frame.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]frame.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]frame.obj [.src.widget]frame.c
$ endif
$ if f$search("[.src.widget]image.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]image.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]image.obj [.src.widget]image.c
$ endif
$ if f$search("[.src.widget]label.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]label.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]label.obj [.src.widget]label.c
$ endif
$ if f$search("[.src.widget]listbox.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]listbox.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]listbox.obj [.src.widget]listbox.c
$ endif
$ if f$search("[.src.widget]menu.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]menu.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]menu.obj [.src.widget]menu.c
$ endif
$ if f$search("[.src.widget]numberentry.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]numberentry.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]numberentry.obj [.src.widget]numberentry.c
$ endif
$ if f$search("[.src.widget]progressbar.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]progressbar.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]progressbar.obj [.src.widget]progressbar.c
$ endif
$ if f$search("[.src.widget]radiobox.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]radiobox.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]radiobox.obj [.src.widget]radiobox.c
$ endif
$ if f$search("[.src.widget]scrollbar.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]scrollbar.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]scrollbar.obj [.src.widget]scrollbar.c
$ endif
$ if f$search("[.src.widget]separator.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]separator.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]separator.obj [.src.widget]separator.c
$ endif
$ if f$search("[.src.widget]submenu.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]submenu.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]submenu.obj [.src.widget]submenu.c
$ endif
$ if f$search("[.src.widget]treeview.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]treeview.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]treeview.obj [.src.widget]treeview.c
$ endif
$ if f$search("[.src.widget]viewport.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]viewport.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]viewport.obj [.src.widget]viewport.c
$ endif
$ if f$search("[.src.widget]window.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]window.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]window.obj [.src.widget]window.c
$ endif
$ if f$search("[.src.widget]box.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.widget]box.obj"
$ cc /include_directory=("./include","./src/widget") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.widget]box.obj [.src.widget]box.c
$ endif
$ if f$search("[.src.dialog]colorpicker.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.dialog]colorpicker.obj"
$ cc /include_directory=("./include","./src/dialog") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.dialog]colorpicker.obj [.src.dialog]colorpicker.c
$ endif
$ if f$search("[.src.dialog]directorychooser.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.dialog]directorychooser.obj"
$ cc /include_directory=("./include","./src/dialog") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.dialog]directorychooser.obj [.src.dialog]directorychooser.c
$ endif
$ if f$search("[.src.dialog]filechooser.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.dialog]filechooser.obj"
$ cc /include_directory=("./include","./src/dialog") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.dialog]filechooser.obj [.src.dialog]filechooser.c
$ endif
$ if f$search("[.src.dialog]messagebox.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.dialog]messagebox.obj"
$ cc /include_directory=("./include","./src/dialog") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.dialog]messagebox.obj [.src.dialog]messagebox.c
$ endif
$ if f$search("[.src.font]boldfont.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.font]boldfont.obj"
$ cc /include_directory=("./include","./src/font") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.font]boldfont.obj [.src.font]boldfont.c
$ endif
$ if f$search("[.src.font]boldttf.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.font]boldttf.obj"
$ cc /include_directory=("./include","./src/font") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.font]boldttf.obj [.src.font]boldttf.c
$ endif
$ if f$search("[.src.font]font.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.font]font.obj"
$ cc /include_directory=("./include","./src/font") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.font]font.obj [.src.font]font.c
$ endif
$ if f$search("[.src.font]ttf.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.font]ttf.obj"
$ cc /include_directory=("./include","./src/font") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.font]ttf.obj [.src.font]ttf.c
$ endif
$ if f$search("[.src.icon]back.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]back.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]back.obj [.src.icon]back.c
$ endif
$ if f$search("[.src.icon]clock.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]clock.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]clock.obj [.src.icon]clock.c
$ endif
$ if f$search("[.src.icon]computer.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]computer.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]computer.obj [.src.icon]computer.c
$ endif
$ if f$search("[.src.icon]directory.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]directory.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]directory.obj [.src.icon]directory.c
$ endif
$ if f$search("[.src.icon]down.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]down.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]down.obj [.src.icon]down.c
$ endif
$ if f$search("[.src.icon]error.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]error.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]error.obj [.src.icon]error.c
$ endif
$ if f$search("[.src.icon]file.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]file.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]file.obj [.src.icon]file.c
$ endif
$ if f$search("[.src.icon]forward.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]forward.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]forward.obj [.src.icon]forward.c
$ endif
$ if f$search("[.src.icon]info.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]info.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]info.obj [.src.icon]info.c
$ endif
$ if f$search("[.src.icon]left.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]left.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]left.obj [.src.icon]left.c
$ endif
$ if f$search("[.src.icon]news.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]news.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]news.obj [.src.icon]news.c
$ endif
$ if f$search("[.src.icon]note.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]note.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]note.obj [.src.icon]note.c
$ endif
$ if f$search("[.src.icon]right.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]right.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]right.obj [.src.icon]right.c
$ endif
$ if f$search("[.src.icon]search.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]search.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]search.obj [.src.icon]search.c
$ endif
$ if f$search("[.src.icon]up.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]up.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]up.obj [.src.icon]up.c
$ endif
$ if f$search("[.src.icon]warning.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.icon]warning.obj"
$ cc /include_directory=("./include","./src/icon") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.icon]warning.obj [.src.icon]warning.c
$ endif
$ if f$search("[.src.abstract]directory.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.abstract]directory.obj"
$ cc /include_directory=("./include","./src/abstract") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.abstract]directory.obj [.src.abstract]directory.c
$ endif
$ if f$search("[.src.abstract]dynamic.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.abstract]dynamic.obj"
$ cc /include_directory=("./include","./src/abstract") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.abstract]dynamic.obj [.src.abstract]dynamic.c
$ endif
$ if f$search("[.src.abstract]time.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.abstract]time.obj"
$ cc /include_directory=("./include","./src/abstract") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.abstract]time.obj [.src.abstract]time.c
$ endif
$ if f$search("[.external]stb_ds.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.external]stb_ds.obj"
$ cc /include_directory=("./include","./external") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.external]stb_ds.obj [.external]stb_ds.c
$ endif
$ if f$search("[.src.backend]x11.obj;*") .eqs. ""
$ then
$ write sys$output "CC [.src.backend]x11.obj"
$ cc /include_directory=("./include","./src/backend") /define=(_MILSKO,USE_X11,NO_IMAGE) /object=[.src.backend]x11.obj [.src.backend]x11.c
$ endif
$ if f$search("[.src]MwSHR.exe;*") .eqs. ""
$ then
$ write sys$output "LINK [.src]MwSHR.exe"
$ OPEN /WRITE LINK_OPT LINK.OPT
$ WRITE LINK_OPT "[.src]color.obj"
$ WRITE LINK_OPT "[.src]core.obj"
$ WRITE LINK_OPT "[.src]default.obj"
$ WRITE LINK_OPT "[.src]draw.obj"
$ WRITE LINK_OPT "[.src]error.obj"
$ WRITE LINK_OPT "[.src]lowlevel.obj"
$ WRITE LINK_OPT "[.src]string.obj"
$ WRITE LINK_OPT "[.src]text.obj"
$ WRITE LINK_OPT "[.src]unicode.obj"
$ WRITE LINK_OPT "[.src.cursor]arrow.obj"
$ WRITE LINK_OPT "[.src.cursor]cross.obj"
$ WRITE LINK_OPT "[.src.cursor]default.obj"
$ WRITE LINK_OPT "[.src.cursor]hidden.obj"
$ WRITE LINK_OPT "[.src.cursor]text.obj"
$ WRITE LINK_OPT "[.src.widget]button.obj"
$ WRITE LINK_OPT "[.src.widget]checkbox.obj"
$ WRITE LINK_OPT "[.src.widget]combobox.obj"
$ WRITE LINK_OPT "[.src.widget]entry.obj"
$ WRITE LINK_OPT "[.src.widget]frame.obj"
$ WRITE LINK_OPT "[.src.widget]image.obj"
$ WRITE LINK_OPT "[.src.widget]label.obj"
$ WRITE LINK_OPT "[.src.widget]listbox.obj"
$ WRITE LINK_OPT "[.src.widget]menu.obj"
$ WRITE LINK_OPT "[.src.widget]numberentry.obj"
$ WRITE LINK_OPT "[.src.widget]progressbar.obj"
$ WRITE LINK_OPT "[.src.widget]radiobox.obj"
$ WRITE LINK_OPT "[.src.widget]scrollbar.obj"
$ WRITE LINK_OPT "[.src.widget]separator.obj"
$ WRITE LINK_OPT "[.src.widget]submenu.obj"
$ WRITE LINK_OPT "[.src.widget]treeview.obj"
$ WRITE LINK_OPT "[.src.widget]viewport.obj"
$ WRITE LINK_OPT "[.src.widget]window.obj"
$ WRITE LINK_OPT "[.src.widget]box.obj"
$ WRITE LINK_OPT "[.src.dialog]colorpicker.obj"
$ WRITE LINK_OPT "[.src.dialog]directorychooser.obj"
$ WRITE LINK_OPT "[.src.dialog]filechooser.obj"
$ WRITE LINK_OPT "[.src.dialog]messagebox.obj"
$ WRITE LINK_OPT "[.src.font]boldfont.obj"
$ WRITE LINK_OPT "[.src.font]boldttf.obj"
$ WRITE LINK_OPT "[.src.font]font.obj"
$ WRITE LINK_OPT "[.src.font]ttf.obj"
$ WRITE LINK_OPT "[.src.icon]back.obj"
$ WRITE LINK_OPT "[.src.icon]clock.obj"
$ WRITE LINK_OPT "[.src.icon]computer.obj"
$ WRITE LINK_OPT "[.src.icon]directory.obj"
$ WRITE LINK_OPT "[.src.icon]down.obj"
$ WRITE LINK_OPT "[.src.icon]error.obj"
$ WRITE LINK_OPT "[.src.icon]file.obj"
$ WRITE LINK_OPT "[.src.icon]forward.obj"
$ WRITE LINK_OPT "[.src.icon]info.obj"
$ WRITE LINK_OPT "[.src.icon]left.obj"
$ WRITE LINK_OPT "[.src.icon]news.obj"
$ WRITE LINK_OPT "[.src.icon]note.obj"
$ WRITE LINK_OPT "[.src.icon]right.obj"
$ WRITE LINK_OPT "[.src.icon]search.obj"
$ WRITE LINK_OPT "[.src.icon]up.obj"
$ WRITE LINK_OPT "[.src.icon]warning.obj"
$ WRITE LINK_OPT "[.src.abstract]directory.obj"
$ WRITE LINK_OPT "[.src.abstract]dynamic.obj"
$ WRITE LINK_OPT "[.src.abstract]time.obj"
$ WRITE LINK_OPT "[.external]stb_ds.obj"
$ WRITE LINK_OPT "[.src.backend]x11.obj"
$ WRITE LINK_OPT "SYS$LIBRARY:DECW$XLIBSHR/SHARE/SHARE"
$ WRITE LINK_OPT "SYS$LIBRARY:DPML$SHR/SHARE/SHARE"
$ CLOSE LINK_OPT
$ link /SHAREABLE=[.src]MwSHR.exe LINK.OPT/options
$ DELETE LINK.OPT;*
$ endif

63
vms/clean.com Normal file
View File

@@ -0,0 +1,63 @@
$ if f$search("[.src]color.obj") .nes. "" then delete [.src]color.obj;*
$ if f$search("[.src]core.obj") .nes. "" then delete [.src]core.obj;*
$ if f$search("[.src]default.obj") .nes. "" then delete [.src]default.obj;*
$ if f$search("[.src]draw.obj") .nes. "" then delete [.src]draw.obj;*
$ if f$search("[.src]error.obj") .nes. "" then delete [.src]error.obj;*
$ if f$search("[.src]lowlevel.obj") .nes. "" then delete [.src]lowlevel.obj;*
$ if f$search("[.src]string.obj") .nes. "" then delete [.src]string.obj;*
$ if f$search("[.src]text.obj") .nes. "" then delete [.src]text.obj;*
$ if f$search("[.src]unicode.obj") .nes. "" then delete [.src]unicode.obj;*
$ if f$search("[.src.cursor]arrow.obj") .nes. "" then delete [.src.cursor]arrow.obj;*
$ if f$search("[.src.cursor]cross.obj") .nes. "" then delete [.src.cursor]cross.obj;*
$ if f$search("[.src.cursor]default.obj") .nes. "" then delete [.src.cursor]default.obj;*
$ if f$search("[.src.cursor]hidden.obj") .nes. "" then delete [.src.cursor]hidden.obj;*
$ if f$search("[.src.cursor]text.obj") .nes. "" then delete [.src.cursor]text.obj;*
$ if f$search("[.src.widget]button.obj") .nes. "" then delete [.src.widget]button.obj;*
$ if f$search("[.src.widget]checkbox.obj") .nes. "" then delete [.src.widget]checkbox.obj;*
$ if f$search("[.src.widget]combobox.obj") .nes. "" then delete [.src.widget]combobox.obj;*
$ if f$search("[.src.widget]entry.obj") .nes. "" then delete [.src.widget]entry.obj;*
$ if f$search("[.src.widget]frame.obj") .nes. "" then delete [.src.widget]frame.obj;*
$ if f$search("[.src.widget]image.obj") .nes. "" then delete [.src.widget]image.obj;*
$ if f$search("[.src.widget]label.obj") .nes. "" then delete [.src.widget]label.obj;*
$ if f$search("[.src.widget]listbox.obj") .nes. "" then delete [.src.widget]listbox.obj;*
$ if f$search("[.src.widget]menu.obj") .nes. "" then delete [.src.widget]menu.obj;*
$ if f$search("[.src.widget]numberentry.obj") .nes. "" then delete [.src.widget]numberentry.obj;*
$ if f$search("[.src.widget]progressbar.obj") .nes. "" then delete [.src.widget]progressbar.obj;*
$ if f$search("[.src.widget]radiobox.obj") .nes. "" then delete [.src.widget]radiobox.obj;*
$ if f$search("[.src.widget]scrollbar.obj") .nes. "" then delete [.src.widget]scrollbar.obj;*
$ if f$search("[.src.widget]separator.obj") .nes. "" then delete [.src.widget]separator.obj;*
$ if f$search("[.src.widget]submenu.obj") .nes. "" then delete [.src.widget]submenu.obj;*
$ if f$search("[.src.widget]treeview.obj") .nes. "" then delete [.src.widget]treeview.obj;*
$ if f$search("[.src.widget]viewport.obj") .nes. "" then delete [.src.widget]viewport.obj;*
$ if f$search("[.src.widget]window.obj") .nes. "" then delete [.src.widget]window.obj;*
$ if f$search("[.src.widget]box.obj") .nes. "" then delete [.src.widget]box.obj;*
$ if f$search("[.src.dialog]colorpicker.obj") .nes. "" then delete [.src.dialog]colorpicker.obj;*
$ if f$search("[.src.dialog]directorychooser.obj") .nes. "" then delete [.src.dialog]directorychooser.obj;*
$ if f$search("[.src.dialog]filechooser.obj") .nes. "" then delete [.src.dialog]filechooser.obj;*
$ if f$search("[.src.dialog]messagebox.obj") .nes. "" then delete [.src.dialog]messagebox.obj;*
$ if f$search("[.src.font]boldfont.obj") .nes. "" then delete [.src.font]boldfont.obj;*
$ if f$search("[.src.font]boldttf.obj") .nes. "" then delete [.src.font]boldttf.obj;*
$ if f$search("[.src.font]font.obj") .nes. "" then delete [.src.font]font.obj;*
$ if f$search("[.src.font]ttf.obj") .nes. "" then delete [.src.font]ttf.obj;*
$ if f$search("[.src.icon]back.obj") .nes. "" then delete [.src.icon]back.obj;*
$ if f$search("[.src.icon]clock.obj") .nes. "" then delete [.src.icon]clock.obj;*
$ if f$search("[.src.icon]computer.obj") .nes. "" then delete [.src.icon]computer.obj;*
$ if f$search("[.src.icon]directory.obj") .nes. "" then delete [.src.icon]directory.obj;*
$ if f$search("[.src.icon]down.obj") .nes. "" then delete [.src.icon]down.obj;*
$ if f$search("[.src.icon]error.obj") .nes. "" then delete [.src.icon]error.obj;*
$ if f$search("[.src.icon]file.obj") .nes. "" then delete [.src.icon]file.obj;*
$ if f$search("[.src.icon]forward.obj") .nes. "" then delete [.src.icon]forward.obj;*
$ if f$search("[.src.icon]info.obj") .nes. "" then delete [.src.icon]info.obj;*
$ if f$search("[.src.icon]left.obj") .nes. "" then delete [.src.icon]left.obj;*
$ if f$search("[.src.icon]news.obj") .nes. "" then delete [.src.icon]news.obj;*
$ if f$search("[.src.icon]note.obj") .nes. "" then delete [.src.icon]note.obj;*
$ if f$search("[.src.icon]right.obj") .nes. "" then delete [.src.icon]right.obj;*
$ if f$search("[.src.icon]search.obj") .nes. "" then delete [.src.icon]search.obj;*
$ if f$search("[.src.icon]up.obj") .nes. "" then delete [.src.icon]up.obj;*
$ if f$search("[.src.icon]warning.obj") .nes. "" then delete [.src.icon]warning.obj;*
$ if f$search("[.src.abstract]directory.obj") .nes. "" then delete [.src.abstract]directory.obj;*
$ if f$search("[.src.abstract]dynamic.obj") .nes. "" then delete [.src.abstract]dynamic.obj;*
$ if f$search("[.src.abstract]time.obj") .nes. "" then delete [.src.abstract]time.obj;*
$ if f$search("[.external]stb_ds.obj") .nes. "" then delete [.external]stb_ds.obj;*
$ if f$search("[.src.backend]x11.obj") .nes. "" then delete [.src.backend]x11.obj;*
$ if f$search("[.src]MwSHR.exe") .nes. "" then delete [.src]MwSHR.exe;*