Compare commits
3 Commits
Author | SHA1 | Date |
---|---|---|
|
fecbab8d69 | |
|
fea45b2d5b | |
|
ab9fcbf6ee |
|
@ -1,97 +0,0 @@
|
|||
Contributor Covenant Code of Conduct
|
||||
Our Pledge
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||
identity and orientation.
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
Our Standards
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall
|
||||
community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||
any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others’ private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
Enforcement Responsibilities
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
Scope
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
Enforcement
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
wherever Pietro Gagliardi may be contacted privately.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
Enforcement Guidelines
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
1. Correction
|
||||
Community Impact: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
Consequence: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
2. Warning
|
||||
Community Impact: A violation through a single incident or series of
|
||||
actions.
|
||||
Consequence: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or permanent
|
||||
ban.
|
||||
3. Temporary Ban
|
||||
Community Impact: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
Consequence: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
4. Permanent Ban
|
||||
Community Impact: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
Consequence: A permanent ban from any sort of public interaction within the
|
||||
community.
|
||||
Attribution
|
||||
This Code of Conduct is adapted from the Contributor Covenant,
|
||||
version 2.1, available at
|
||||
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
||||
Community Impact Guidelines were inspired by
|
||||
Mozilla’s code of conduct enforcement ladder.
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
|
107
Compatibility.md
107
Compatibility.md
|
@ -19,18 +19,24 @@ TODO look up PDC 2008 talk "new shell user interface"
|
|||
## GTK+
|
||||
TODO what ships with Ubuntu Quantal (12.10)?
|
||||
|
||||
### GTK+ 3.6
|
||||
ships with: Ubuntu Raring (13.04)
|
||||
|
||||
- GtkEntry and GtkTextView have input purposes and input hints for external input methods but do not change input themselves
|
||||
- according to Company, we connect to insert-text for that
|
||||
- GtkLevelBar
|
||||
- GtkMenuButton
|
||||
- **GtkSearchEntry**
|
||||
|
||||
### GTK+ 3.8
|
||||
ships with: Ubuntu Saucy (13.10)
|
||||
|
||||
Not many interesting new things to us here, unless you count widget-internal tickers and single-click instead of double-click to select list items (a la KDE)... and oh yeah, also widget opacity.
|
||||
|
||||
### GTK+ 3.10
|
||||
ships with: **Ubuntu Trusty (14.04 LTS)**
|
||||
<br>GLib version: 2.40
|
||||
|
||||
minimum versions (see `configure.ac` for the relevant tagged 3.x.0 versions):
|
||||
- GLib: 2.37.5
|
||||
- ATK: 2.7.5
|
||||
- cairo: 1.12.0
|
||||
- pango: 1.32.4
|
||||
- gdk-pixbuf: 2.27.1
|
||||
|
||||
features:
|
||||
- tab character stops in GtkEntry
|
||||
- GtkHeaderBar
|
||||
- intended for titlebar overrides; GtkInfoBar is what I keep thinking GtkHeaderBar is
|
||||
|
@ -44,14 +50,6 @@ features:
|
|||
ships with: Ubuntu Utopic (14.10)
|
||||
<br>GLib version: 2.42
|
||||
|
||||
minimum versions:
|
||||
- GLib: 2.39.5
|
||||
- ATK: 2.7.5
|
||||
- cairo: 1.12.0
|
||||
- pango: 1.32.4
|
||||
- gdk-pixbuf: 2.27.1
|
||||
|
||||
features:
|
||||
- GtkActionBar (basically like the bottom-of-the-window toolbars in Mac programs)
|
||||
- gtk_get_locale_direction(), for internationalization
|
||||
- more control over GtkHeaderBar
|
||||
|
@ -64,14 +62,6 @@ features:
|
|||
ships with: **Debian Jessie**, Ubuntu Vivid (15.04)
|
||||
<br>GLib version: Debian: 2.42, Ubuntu: 2.44
|
||||
|
||||
minimum versions:
|
||||
- GLib: 2.41.2
|
||||
- ATK: 2.12.0
|
||||
- cairo: 1.12.0
|
||||
- pango: 1.36.7
|
||||
- gdk-pixbuf: 2.30.0
|
||||
|
||||
features:
|
||||
- gestures
|
||||
- better GtkListbox selection handling
|
||||
- more style classes (TODO also prior?)
|
||||
|
@ -81,14 +71,6 @@ features:
|
|||
ships with: Ubuntu Wily (15.10)
|
||||
<br>GLib version: 2.46
|
||||
|
||||
minimum versions:
|
||||
- GLib: 2.43.4
|
||||
- ATK: 2.15.1
|
||||
- cairo: 1.14.0
|
||||
- pango: 1.36.7
|
||||
- gdk-pixbuf: 2.30.0
|
||||
|
||||
features:
|
||||
- gtk_clipboard_get_default() (???)
|
||||
- **GtkGLArea**
|
||||
- proper xalign and yalign for GtkLabel; should get rid of runtime deprecation warnings
|
||||
|
@ -104,69 +86,8 @@ features:
|
|||
- GtkTextView: font fallbacks
|
||||
|
||||
### GTK+ 3.18
|
||||
ships with: TODO
|
||||
|
||||
minimum versions:
|
||||
- GLib: 2.45.8 (min_required 2.44 max_allowed 2.46 ?)
|
||||
- ATK: 2.15.1
|
||||
- cairo: 1.14.0
|
||||
- pango: 1.37.3
|
||||
- gdk-pixbuf: 2.30.0
|
||||
|
||||
features:
|
||||
- TODO
|
||||
|
||||
### GTK+ 3.20
|
||||
ships with: TODO
|
||||
|
||||
minimum versions (TODO double-check these):
|
||||
- GLib: 2.45.8 (min_required 2.44 max_allowed 2.46 ?)
|
||||
- ATK: 2.15.1
|
||||
- cairo: 1.14.0
|
||||
- pango: 1.37.3
|
||||
- gdk-pixbuf: 2.30.0
|
||||
|
||||
features:
|
||||
- TODO
|
||||
|
||||
### GTK+ 3.22
|
||||
ships with: TODO
|
||||
|
||||
minimum versions:
|
||||
- GLib: 2.49.4 (min_required 2.48 max_allowed 2.50 ?)
|
||||
- ATK: 2.15.1
|
||||
- cairo: 1.14.0
|
||||
- pango: 1.37.3
|
||||
- gdk-pixbuf: 2.30.0
|
||||
|
||||
features:
|
||||
- TODO
|
||||
|
||||
### GTK+ 3.24
|
||||
ships with: TODO
|
||||
|
||||
minimum versions:
|
||||
- GLib: 2.49.4 (min_required 2.48 max_allowed 2.50 ?)
|
||||
- ATK: 2.15.1
|
||||
- cairo: 1.14.0
|
||||
- pango: 1.41.0
|
||||
- gdk-pixbuf: 2.30.0
|
||||
|
||||
features:
|
||||
- TODO
|
||||
|
||||
### TODO greater versions
|
||||
ships with: TODO
|
||||
|
||||
minimum versions:
|
||||
- GLib: TODO (min_required TODO max_allowed TODO ?)
|
||||
- ATK: TODO
|
||||
- cairo: TODO
|
||||
- pango: TODO
|
||||
- gdk-pixbuf: TODO
|
||||
|
||||
features:
|
||||
- TODO
|
||||
|
||||
## Cocoa
|
||||
### Mac OS X 10.8
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
all:
|
||||
|
||||
redomod:
|
||||
rm -f go.*
|
||||
GO111MODULE= go mod init
|
||||
GO111MODULE= go mod tidy
|
||||
|
|
@ -30,10 +30,6 @@ But libui is not dead; I am working on it whenever I can, and I hope to get it t
|
|||
|
||||
*Note that today's entry (Eastern Time) may be updated later today.*
|
||||
|
||||
* **<codedate**
|
||||
* **BIG CHANGES TODO INCLUDING DOCUMENTATION** TODO TODO TODO TODO You can read the documentation for more details, but the most important notes to know:
|
||||
* Static builds now require users of libui to define `uiStatic` before including `ui.h`.
|
||||
|
||||
* **7 April 2019**
|
||||
* **The build system has been switched to Meson.** See below for instructions. This change was made because the previous build system, CMake, caused countless headaches over trivial issues. Meson was chosen due to how unproblematic setting up libui's build just right was, as well as having design goals that are by coincidence closely aligned with what libui wants.
|
||||
* Travis CI has been replaced with Azure Pipelines and much of the AppVeyor CI configuration was integrated into the Azure Pipelines configuration. This shouldn't affect most developers.
|
||||
|
@ -170,7 +166,7 @@ Nim | [ui](https://github.com/nim-lang/ui)
|
|||
Perl6 | [perl6-libui](https://github.com/Garland-g/perl6-libui)
|
||||
PHP | [ui](https://github.com/krakjoe/ui)
|
||||
Python | [pylibui](https://github.com/joaoventura/pylibui)
|
||||
Ruby | [libui-ruby](https://github.com/jamescook/libui-ruby)
|
||||
Ruby | [libui-ruby](https://github.com/jamescook/libui-ruby), [libui](https://github.com/kojix2/libui)
|
||||
Rust | [libui-rs](https://github.com/rust-native-ui/libui-rs)
|
||||
Scala | [scalaui](https://github.com/lolgab/scalaui)
|
||||
Swift | [libui-swift](https://github.com/sclukey/libui-swift)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// cl winbuttonexplorertheme.cpp -MT -link user32.lib kernel32.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib _res\windows.res
|
||||
// cl winbuttonexplorertheme.cpp -MT -link user32.lib kernel32.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib windows.res
|
||||
|
||||
void diele(const char *func)
|
||||
{
|
||||
|
|
|
@ -1,492 +0,0 @@
|
|||
// 31 august 2019
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
#define STRICT
|
||||
#define STRICT_TYPED_ITEMIDS
|
||||
#define WINVER 0x0600 /* from Microsoft's winnls.h */
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#define _WIN32_WINDOWS 0x0600 /* from Microsoft's pdh.h */
|
||||
#define _WIN32_IE 0x0700
|
||||
#define NTDDI_VERSION 0x06000000
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <uxtheme.h>
|
||||
#include <vsstyle.h>
|
||||
#include <vssym32.h>
|
||||
#include <windowsx.h>
|
||||
#include <dwmapi.h>
|
||||
#include "_res/detours.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// cl windwmblurbehindtest.cpp -MT -link user32.lib kernel32.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib dwmapi.lib _res\detours.lib _res\windows.res
|
||||
|
||||
void diele(const char *func)
|
||||
{
|
||||
DWORD le;
|
||||
|
||||
le = GetLastError();
|
||||
fprintf(stderr, "%s: %I32u\n", func, le);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void diehr(const char *func, HRESULT hr)
|
||||
{
|
||||
fprintf(stderr, "%s: 0x%08I32X\n", func, hr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// TODO if we merge this into libui proper, this will need to be deduplicated
|
||||
static inline HRESULT lastErrorToHRESULT(DWORD lastError)
|
||||
{
|
||||
if (lastError == 0)
|
||||
return E_FAIL;
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
}
|
||||
|
||||
static void paintIntoBuffer(HWND hwnd, UINT uMsg, HDC dc, RECT *r)
|
||||
{
|
||||
HPAINTBUFFER bbuf;
|
||||
HDC bdc;
|
||||
HRESULT hr;
|
||||
|
||||
// TODO begin check errors
|
||||
bbuf = BeginBufferedPaint(dc, r, BPBF_TOPDOWNDIB, NULL, &bdc);
|
||||
if (uMsg == WM_PAINT)
|
||||
SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM) bdc, PRF_CLIENT | PRF_ERASEBKGND);
|
||||
else
|
||||
SendMessageW(hwnd, WM_PRINT, (WPARAM) bdc, PRF_ERASEBKGND | PRF_NONCLIENT);
|
||||
hr = BufferedPaintSetAlpha(bbuf, NULL, 255);
|
||||
hr = EndBufferedPaint(bbuf, TRUE);
|
||||
// TODO end check errors
|
||||
}
|
||||
|
||||
static HWND bpHWND = NULL;
|
||||
static HDC bpDC = NULL;
|
||||
static HDC bpPSDC = NULL;
|
||||
static HDC bpBufDC = NULL;
|
||||
static HPAINTBUFFER bpBuf = NULL;
|
||||
|
||||
static HDC (WINAPI *origBeginPaint)(HWND hwnd, LPPAINTSTRUCT ps) = BeginPaint;
|
||||
static HDC WINAPI ourBeginPaint(HWND hwnd, LPPAINTSTRUCT ps)
|
||||
{
|
||||
HDC dc, bdc;
|
||||
HPAINTBUFFER bbuf;
|
||||
|
||||
if (bpHWND == NULL) {
|
||||
dc = (*origBeginPaint)(hwnd, ps);
|
||||
if (dc == NULL)
|
||||
return NULL;
|
||||
bbuf = BeginBufferedPaint(dc, &(ps->rcPaint), BPBF_TOPDOWNDIB, NULL, &bdc);
|
||||
if (bbuf == NULL) // just draw normally, not much else we can do but deal with the graphical glitches
|
||||
return dc;
|
||||
bpHWND = hwnd;
|
||||
bpDC = dc;
|
||||
bpPSDC = ps->hdc;
|
||||
ps->hdc = bdc;
|
||||
bpBufDC = bdc;
|
||||
bpBuf = bbuf;
|
||||
return bdc;
|
||||
}
|
||||
return (*origBeginPaint)(hwnd, ps);
|
||||
}
|
||||
|
||||
static HANIMATIONBUFFER bpHAB = NULL;
|
||||
static HDC bpFromDC = NULL;
|
||||
static HDC bpFromBufDC = NULL;
|
||||
static HPAINTBUFFER bpFromBuf = NULL;
|
||||
static HDC bpToDC = NULL;
|
||||
static HDC bpToBufDC = NULL;
|
||||
static HPAINTBUFFER bpToBuf = NULL;
|
||||
|
||||
static HANIMATIONBUFFER (STDAPICALLTYPE *origBeginBufferedAnimation)(HWND hwnd, HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, BP_ANIMATIONPARAMS *pAnimationParams, HDC *phdcFrom, HDC *phdcTo) = BeginBufferedAnimation;
|
||||
static HANIMATIONBUFFER STDAPICALLTYPE ourBeginBufferedAnimation(HWND hwnd, HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, BP_ANIMATIONPARAMS *pAnimationParams, HDC *phdcFrom, HDC *phdcTo)
|
||||
{
|
||||
HANIMATIONBUFFER hab;
|
||||
HDC bdc;
|
||||
HPAINTBUFFER bbuf;
|
||||
bool doit;
|
||||
|
||||
doit = false;
|
||||
if (bpHWND != NULL && bpHWND == hwnd && bpBufDC != NULL && bpBufDC == hdcTarget) {
|
||||
doit = true;
|
||||
hdcTarget = bpDC;
|
||||
}
|
||||
hab = (*origBeginBufferedAnimation)(hwnd, hdcTarget, prcTarget, dwFormat, pPaintParams, pAnimationParams, phdcFrom, phdcTo);
|
||||
if (!doit)
|
||||
return hab;
|
||||
if (hab == NULL)
|
||||
return NULL;
|
||||
bpHAB = hab;
|
||||
if (phdcFrom != NULL && *phdcFrom != NULL) {
|
||||
bbuf = BeginBufferedPaint(*phdcFrom, prcTarget, BPBF_TOPDOWNDIB, NULL, &bdc);
|
||||
if (bbuf != NULL) { // otherwise, just draw normally, not much else we can do but deal with the graphical glitches
|
||||
bpFromDC = *phdcFrom;
|
||||
*phdcFrom = bdc;
|
||||
bpFromBufDC = bdc;
|
||||
bpFromBuf = bbuf;
|
||||
}
|
||||
}
|
||||
if (phdcTo != NULL && *phdcTo != NULL) {
|
||||
bbuf = BeginBufferedPaint(*phdcTo, prcTarget, BPBF_TOPDOWNDIB, NULL, &bdc);
|
||||
if (bbuf != NULL) {
|
||||
bpToDC = *phdcTo;
|
||||
*phdcTo = bdc;
|
||||
bpToBufDC = bdc;
|
||||
bpToBuf = bbuf;
|
||||
}
|
||||
}
|
||||
return hab;
|
||||
}
|
||||
|
||||
static BOOL (STDAPICALLTYPE *origBufferedPaintRenderAnimation)(HWND hwnd, HDC hdcTarget) = BufferedPaintRenderAnimation;
|
||||
static BOOL STDAPICALLTYPE ourBufferedPaintRenderAnimation(HWND hwnd, HDC hdcTarget)
|
||||
{
|
||||
if (bpHWND != NULL && bpHWND == hwnd && bpBufDC != NULL && bpBufDC == hdcTarget)
|
||||
hdcTarget = bpDC;
|
||||
return (*origBufferedPaintRenderAnimation)(hwnd, hdcTarget);
|
||||
}
|
||||
|
||||
static HRESULT (STDAPICALLTYPE *origEndBufferedAnimation)(HANIMATIONBUFFER hbpAnimation, BOOL fUpdateTarget) = EndBufferedAnimation;
|
||||
static HRESULT STDAPICALLTYPE ourEndBufferedAnimation(HANIMATIONBUFFER hbpAnimation, BOOL fUpdateTarget)
|
||||
{
|
||||
HRESULT hrFrom1 = S_OK;
|
||||
HRESULT hrFrom2 = S_OK;
|
||||
HRESULT hrTo1 = S_OK;
|
||||
HRESULT hrTo2 = S_OK;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (bpHAB != NULL && bpHAB == hbpAnimation) {
|
||||
if (bpFromDC != NULL) {
|
||||
hrFrom1 = BufferedPaintSetAlpha(bpFromBuf, NULL, 255);
|
||||
hrFrom2 = EndBufferedPaint(bpFromBuf, TRUE);
|
||||
bpFromDC = NULL;
|
||||
bpFromBufDC = NULL;
|
||||
bpFromBuf = NULL;
|
||||
}
|
||||
if (bpToDC != NULL) {
|
||||
hrTo1 = BufferedPaintSetAlpha(bpToBuf, NULL, 255);
|
||||
hrTo2 = EndBufferedPaint(bpToBuf, TRUE);
|
||||
bpToDC = NULL;
|
||||
bpToBufDC = NULL;
|
||||
bpToBuf = NULL;
|
||||
}
|
||||
bpHAB = NULL;
|
||||
}
|
||||
hr = (*origEndBufferedAnimation)(hbpAnimation, fUpdateTarget);
|
||||
if (hrFrom1 != S_OK)
|
||||
return hrFrom1;
|
||||
if (hrFrom2 != S_OK)
|
||||
return hrFrom2;
|
||||
if (hrTo1 != S_OK)
|
||||
return hrTo1;
|
||||
if (hrTo2 != S_OK)
|
||||
return hrTo2;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static BOOL (WINAPI *origEndPaint)(HWND hwnd, CONST PAINTSTRUCT *ps) = EndPaint;
|
||||
static BOOL WINAPI ourEndPaint(HWND hwnd, CONST PAINTSTRUCT *ps)
|
||||
{
|
||||
HRESULT hr1, hr2;
|
||||
BOOL ret;
|
||||
DWORD lasterr;
|
||||
|
||||
if (bpHWND == NULL || bpHWND != hwnd)
|
||||
return (*origEndPaint)(hwnd, ps);
|
||||
// TODO don't const this
|
||||
((PAINTSTRUCT *) ps)->hdc = bpPSDC;
|
||||
hr1 = BufferedPaintSetAlpha(bpBuf, NULL, 255);
|
||||
hr2 = EndBufferedPaint(bpBuf, TRUE);
|
||||
ret = (*origEndPaint)(hwnd, ps);
|
||||
lasterr = GetLastError();
|
||||
bpHWND = NULL;
|
||||
bpDC = NULL;
|
||||
bpPSDC = NULL;
|
||||
bpBufDC = NULL;
|
||||
bpBuf = NULL;
|
||||
if (hr1 != S_OK) {
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
if (HRESULT_FACILITY(hr1) == FACILITY_WIN32)
|
||||
SetLastError(HRESULT_CODE(hr1));
|
||||
return 0;
|
||||
}
|
||||
if (hr2 != S_OK) {
|
||||
SetLastError(ERROR_GEN_FAILURE);
|
||||
if (HRESULT_FACILITY(hr2) == FACILITY_WIN32)
|
||||
SetLastError(HRESULT_CODE(hr2));
|
||||
return 0;
|
||||
}
|
||||
SetLastError(lasterr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK buttonSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC dc;
|
||||
RECT r;
|
||||
|
||||
switch (uMsg) {
|
||||
case WM_PAINT:
|
||||
// TODO begin check errors
|
||||
#if 0
|
||||
dc = BeginPaint(hwnd, &ps);
|
||||
// paintIntoBuffer(hwnd, uMsg, dc, &(ps.rcPaint));
|
||||
DefSubclassProc(hwnd, uMsg, (WPARAM) dc, lParam);
|
||||
EndPaint(hwnd, &ps);
|
||||
#elif 1
|
||||
if (wParam != 0)
|
||||
break;
|
||||
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourAttach(&((PVOID &) origBeginPaint), ourBeginPaint);
|
||||
DetourAttach(&((PVOID &) origBeginBufferedAnimation), ourBeginBufferedAnimation);
|
||||
//TODO DetourAttach(&((PVOID &) origBufferedPaintRenderAnimation), ourBufferedPaintRenderAnimation);
|
||||
DetourAttach(&((PVOID &) origEndBufferedAnimation), ourEndBufferedAnimation);
|
||||
DetourAttach(&((PVOID &) origEndPaint), ourEndPaint);
|
||||
DetourTransactionCommit();
|
||||
|
||||
DefSubclassProc(hwnd, uMsg, wParam, lParam);
|
||||
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourDetach(&((PVOID &) origBeginPaint), ourBeginPaint);
|
||||
DetourDetach(&((PVOID &) origBeginBufferedAnimation), ourBeginBufferedAnimation);
|
||||
//TODO DetourDetach(&((PVOID &) origBufferedPaintRenderAnimation), ourBufferedPaintRenderAnimation);
|
||||
DetourDetach(&((PVOID &) origEndBufferedAnimation), ourEndBufferedAnimation);
|
||||
DetourDetach(&((PVOID &) origEndPaint), ourEndPaint);
|
||||
DetourTransactionCommit();
|
||||
#else
|
||||
DefSubclassProc(hwnd, uMsg, wParam, lParam);
|
||||
if (0) {
|
||||
RECT r;
|
||||
|
||||
GetClientRect(hwnd, &r);
|
||||
MapWindowRect(hwnd, GetParent(hwnd), &r);
|
||||
InvalidateRect(GetParent(hwnd), &r, TRUE);
|
||||
}
|
||||
#endif
|
||||
// TODO end check errors
|
||||
return 0;
|
||||
//TODO case WM_NCPAINT:
|
||||
// TODO begin check errors
|
||||
dc = GetDCEx(hwnd, (HRGN) wParam, DCX_WINDOW | DCX_INTERSECTRGN);
|
||||
GetRgnBox((HRGN) wParam, &r);
|
||||
paintIntoBuffer(hwnd, uMsg, dc, &r);
|
||||
ReleaseDC(hwnd, dc);
|
||||
// TODO end check errors
|
||||
return 0;
|
||||
case WM_NCDESTROY:
|
||||
if (RemoveWindowSubclass(hwnd, buttonSubProc, uIdSubclass) == FALSE)
|
||||
diele("RemoveWindowSubclass()");
|
||||
break;
|
||||
}
|
||||
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
HINSTANCE hInstance;
|
||||
HRGN rgn;
|
||||
BOOL created = FALSE;
|
||||
HBRUSH opaquebrush;
|
||||
|
||||
#define OURWIDTH 320
|
||||
#define OURHEIGHT 240
|
||||
|
||||
void onWM_CREATE(HWND hwnd)
|
||||
{
|
||||
DWM_BLURBEHIND dbb;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
rgn = CreateRectRgn(0, 0, OURWIDTH / 2, OURHEIGHT);
|
||||
if (rgn == NULL)
|
||||
diele("CreateRectRgn()");
|
||||
ZeroMemory(&dbb, sizeof (DWM_BLURBEHIND));
|
||||
dbb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||
dbb.fEnable = TRUE;
|
||||
dbb.hRgnBlur = NULL;//rgn;
|
||||
hr = DwmEnableBlurBehindWindow(hwnd, &dbb);
|
||||
if (hr != S_OK)
|
||||
diehr("DwmEnableBlurBehindWindow()", hr);
|
||||
HWND w1=CreateWindowExW(0,
|
||||
L"BUTTON",L"Hello",
|
||||
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
|
||||
3*OURWIDTH/4,150,
|
||||
OURWIDTH/6,25,
|
||||
hwnd,NULL,hInstance,NULL);
|
||||
SetWindowSubclass(w1, buttonSubProc, 0, 0);
|
||||
HWND w2=CreateWindowExW(0,
|
||||
L"BUTTON",L"Hello",
|
||||
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
|
||||
3*OURWIDTH/4,200,
|
||||
OURWIDTH/6,25,
|
||||
hwnd,NULL,hInstance,NULL);
|
||||
SetWindowTheme(w2,L"",L"");
|
||||
SetWindowSubclass(w2, buttonSubProc, 0, 0);
|
||||
}
|
||||
|
||||
void doPaint(HWND hwnd, HDC dc, RECT *rcPaint)
|
||||
{
|
||||
RECT r, r2;
|
||||
HPAINTBUFFER bbuf;
|
||||
HDC bdc;
|
||||
HRESULT hr;
|
||||
|
||||
// First, fill with BLACK_BRUSH to satisfy the DWM
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = OURWIDTH;
|
||||
r.bottom = OURHEIGHT;
|
||||
// TODO check error
|
||||
FillRect(dc, &r, (HBRUSH) GetStockObject(BLACK_BRUSH));
|
||||
|
||||
r.left = OURWIDTH / 2;
|
||||
// TODO check error
|
||||
IntersectRect(&r2, &r, rcPaint);
|
||||
bbuf = BeginBufferedPaint(dc, &r, BPBF_TOPDOWNDIB, NULL, &bdc);
|
||||
if (bbuf == NULL)
|
||||
diele("BeginBufferedPaint()");
|
||||
// TODO start check errors
|
||||
FillRect(bdc, &r, GetSysColorBrush(COLOR_BTNFACE));
|
||||
r.left = 3 * OURWIDTH / 4;
|
||||
r.top = 100;
|
||||
r.right = 7 * OURWIDTH / 8;
|
||||
r.bottom = 25;
|
||||
auto m = SetBkMode(bdc,TRANSPARENT);
|
||||
TextOutW(bdc, r.left, r.top, L"Hello", 5);
|
||||
SetBkMode(bdc, m);
|
||||
// TODO end check errors
|
||||
hr = BufferedPaintSetAlpha(bbuf, NULL, 255);
|
||||
if (hr != S_OK)
|
||||
diehr("BufferedPaintSetAlpha()", hr);
|
||||
hr = EndBufferedPaint(bbuf, TRUE);
|
||||
if (hr != S_OK)
|
||||
diehr("EndBufferedPaint()", hr);
|
||||
}
|
||||
|
||||
void onWM_PAINT(HWND hwnd, WPARAM wParam)
|
||||
{
|
||||
HDC dc;
|
||||
PAINTSTRUCT ps;
|
||||
RECT rcPaint;
|
||||
|
||||
if (wParam != 0) {
|
||||
// TODO check errors
|
||||
GetClientRect(hwnd, &rcPaint);
|
||||
doPaint(hwnd, (HDC) wParam, &rcPaint);
|
||||
return;
|
||||
}
|
||||
|
||||
ZeroMemory(&ps, sizeof (PAINTSTRUCT));
|
||||
dc = BeginPaint(hwnd, &ps);
|
||||
if (dc == NULL)
|
||||
diele("BeginPaint()");
|
||||
doPaint(hwnd, dc, &(ps.rcPaint));
|
||||
EndPaint(hwnd, &ps);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg) {
|
||||
case WM_CREATE:
|
||||
onWM_CREATE(hwnd);
|
||||
break;
|
||||
case WM_PAINT:
|
||||
// case WM_PRINTCLIENT:
|
||||
// case WM_ERASEBKGND:
|
||||
onWM_PAINT(hwnd, wParam);
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
STARTUPINFOW si;
|
||||
int nCmdShow;
|
||||
INITCOMMONCONTROLSEX icc;
|
||||
HICON hDefaultIcon;
|
||||
HCURSOR hDefaultCursor;
|
||||
DWORD dwStyle, dwExStyle;
|
||||
RECT r;
|
||||
WNDCLASSW wc;
|
||||
HWND mainwin;
|
||||
MSG msg;
|
||||
HRESULT hr;
|
||||
|
||||
hInstance = (HINSTANCE) (&__ImageBase);
|
||||
nCmdShow = SW_SHOWDEFAULT;
|
||||
GetStartupInfoW(&si);
|
||||
if ((si.dwFlags & STARTF_USESHOWWINDOW) != 0)
|
||||
nCmdShow = si.wShowWindow;
|
||||
|
||||
ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
|
||||
icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
|
||||
icc.dwICC = ICC_STANDARD_CLASSES | ICC_BAR_CLASSES | ICC_COOL_CLASSES;
|
||||
if (InitCommonControlsEx(&icc) == 0)
|
||||
diele("InitCommonControlsEx()");
|
||||
|
||||
hDefaultIcon = LoadIconW(NULL, IDI_APPLICATION);
|
||||
if (hDefaultIcon == NULL)
|
||||
diele("LoadIconW(IDI_APPLICATION)");
|
||||
hDefaultCursor = LoadCursorW(NULL, IDC_ARROW);
|
||||
if (hDefaultCursor == NULL)
|
||||
diele("LoadCursorW(IDC_ARROW)");
|
||||
|
||||
hr = BufferedPaintInit();
|
||||
if (hr != S_OK)
|
||||
diehr("BufferedPaintInit()", hr);
|
||||
|
||||
ZeroMemory(&wc, sizeof (WNDCLASSW));
|
||||
wc.lpszClassName = L"mainwin";
|
||||
wc.lpfnWndProc = wndproc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = hDefaultIcon;
|
||||
wc.hCursor = hDefaultCursor;
|
||||
wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
|
||||
if (RegisterClassW(&wc) == 0)
|
||||
diele("RegisterClassW()");
|
||||
|
||||
dwStyle = WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
|
||||
dwExStyle = 0;
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = OURWIDTH;
|
||||
r.bottom = OURHEIGHT;
|
||||
if (AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle) == 0)
|
||||
diele("AdjustWindowRectEx()");
|
||||
mainwin = CreateWindowExW(dwExStyle,
|
||||
L"mainwin", L"Main Window",
|
||||
dwStyle,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
r.right - r.left, r.bottom - r.top,
|
||||
NULL, NULL, hInstance, NULL);
|
||||
if (mainwin == NULL)
|
||||
diele("CreateWindowExW(L\"mainwin\")");
|
||||
|
||||
ShowWindow(mainwin, nCmdShow);
|
||||
if (UpdateWindow(mainwin) == 0)
|
||||
diele("UpdateWindow()");
|
||||
|
||||
for (;;) {
|
||||
int res;
|
||||
|
||||
res = GetMessageW(&msg, NULL, 0, 0);
|
||||
if (res < 0)
|
||||
diele("GetMessageW()");
|
||||
if (res == 0)
|
||||
break;
|
||||
if (IsDialogMessageW(mainwin, &msg) == 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
BufferedPaintUnInit();
|
||||
return 0;
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// cl winrebarexplorertheme.cpp -MT -link user32.lib kernel32.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib _res\windows.res
|
||||
// cl winrebarexplorertheme.cpp -MT -link user32.lib kernel32.lib gdi32.lib comctl32.lib uxtheme.lib msimg32.lib windows.res
|
||||
|
||||
void diele(const char *func)
|
||||
{
|
||||
|
|
|
@ -23,4 +23,3 @@ alphablending:
|
|||
http://www.os2voice.org/vnewsarc/bn2007122.html
|
||||
http://www.mozillazine.org/talkback.html?article=194
|
||||
https://books.google.com/books?id=9cpU5uYCzq4C&pg=PA202&lpg=PA202&dq=%22OS/2%22+alphablending&source=bl&ots=uatEop2jAL&sig=HAa_ofQSKsk6-8tBR6YZ6MRJG_0&hl=en&sa=X&ved=0ahUKEwiDq5HukLbaAhUk8IMKHR7aCw4Q6AEIWTAI#v=onepage&q=%22OS%2F2%22%20alphablending&f=false
|
||||
investigate eicons.dll
|
||||
|
|
|
@ -21,19 +21,3 @@ https://medium.com/@ivan.ha/how-to-mimic-a-2k-monitor-as-retina-display-in-macos
|
|||
https://www.google.com/search?client=firefox-b-1-d&q=IOFramebuffer+10.13
|
||||
https://www.quora.com/What-is-the-underlying-reason-if-DisplayLink-is-no-longer-working-properly-on-Mac-OS
|
||||
https://github.com/Siguza/iokit-utils
|
||||
https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/BaseClasses/BaseClasses.html#//apple_ref/doc/uid/TP0000016-BAJEEGAF
|
||||
https://github.com/andreacremaschi/EWProxyFramebuffer
|
||||
https://github.com/practicalswift/osx/blob/master/src/iographics/IOGraphicsFamily/IOAccelerator.cpp
|
||||
https://github.com/practicalswift/osx/tree/master/src/iographics/IOGraphicsFamily
|
||||
https://www.google.com/search?q=macos+monitor+driver&client=firefox-b-1-d&ei=zh3QXLOqHcbI_QaQtISABg&start=10&sa=N&ved=0ahUKEwizyb_W6YbiAhVGZN8KHRAaAWAQ8tMDCKgB&biw=1083&bih=606
|
||||
https://www.google.com/search?client=firefox-b-1-d&q=macos+10.13+monitor+driver
|
||||
https://www.google.com/search?client=firefox-b-1-d&q=macos+10.13+monitor+driver+development
|
||||
https://www.kensington.com/news/docking-connectivity-blog/Mac-OS-10.13.4-and-OS-10.14-DisplayLink-Issue-Resolved/
|
||||
https://www.kensington.com/news/docking-connectivity-blog/Mac-OS-10.13.4-and-OS-10.14-DisplayLink-Issue-Resolved/
|
||||
https://www.displaylink.com/downloads
|
||||
https://www.google.com/search?client=firefox-b-1-d&q=macos+10.13+monitor+driver+github
|
||||
https://apple.stackexchange.com/questions/335610/where-do-i-find-macos-graphics-drivers
|
||||
http://www.cgl.ucsf.edu/chimera/graphics/updatemac.html
|
||||
https://support.apple.com/downloads/driver-macbook
|
||||
https://support.apple.com/en_US/downloads/macbookpro
|
||||
https://www.kensington.com/news/docking-connectivity-blog/resolving-mac-os-x-10.13.4-displaylink-issue/
|
||||
|
|
50
_notes/misc
50
_notes/misc
|
@ -211,53 +211,3 @@ whatever this is seems to have no documentation... it appears to be related to
|
|||
unreachable code optimizations
|
||||
https://docs.microsoft.com/en-us/cpp/intrinsics/assume?view=vs-2017
|
||||
https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
|
||||
|
||||
|
||||
(#gtk) [01:57:47] <gwutz2[m]> I have a question about blocking signal handlers from emission when using a GtkSearchEntry. As i did it in the past with signal emissions is to block the handler, set anything on the Entry, unblock the handler. But the search entry emits after 150 ms therefore this does not work for GtkSearchEntrys. Is there a good way to archieve the same?
|
||||
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20191010-00/?p=102978
|
||||
TODO put this in the right file
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20191011-00/?p=102989
|
||||
https://devblogs.microsoft.com/oldnewthing/20191015-00/?p=102996
|
||||
TODO put this one in the right file too?
|
||||
the first one in this block isn't part of that TODO
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20191021-00/?p=103014
|
||||
https://devblogs.microsoft.com/oldnewthing/20191025-00/?p=103025
|
||||
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20191108-00/?p=103080
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20200110-00/?p=103316
|
||||
ribbon https://github.com/MicrosoftDocs/Contribute/issues/267#issuecomment-610717385
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20200730-00/?p=104021
|
||||
https://devblogs.microsoft.com/oldnewthing/20200807-00/?p=104056
|
||||
https://devblogs.microsoft.com/oldnewthing/20200821-00/?p=104112
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20201030-00/?p=104409
|
||||
https://devblogs.microsoft.com/oldnewthing/20201109-00/?p=104431
|
||||
https://devblogs.microsoft.com/oldnewthing/20201123-00/?p=104476
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20201231-00/?p=104627
|
||||
|
||||
autoscroll on drag on windows {
|
||||
https://devblogs.microsoft.com/oldnewthing/20210125-00/?p=104757
|
||||
https://devblogs.microsoft.com/oldnewthing/20210126-00/?p=104759
|
||||
https://devblogs.microsoft.com/oldnewthing/20210127-00/?p=104764
|
||||
https://devblogs.microsoft.com/oldnewthing/20210128-00/?p=104768
|
||||
https://devblogs.microsoft.com/oldnewthing/20210129-00/?p=104773
|
||||
}
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20210202-00/?p=104785
|
||||
|
||||
https://gankra.github.io/blah/text-hates-you/
|
||||
https://lord.io/text-editing-hates-you-too/
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20210526-00/?p=105252
|
||||
|
||||
https://devblogs.microsoft.com/oldnewthing/20210527-00/?p=105255 inclusion and support of icu in newer win10
|
||||
|
||||
https://gitlab.gnome.org/jadahl/libdecoration
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
SGI IRIS 2000
|
||||
sgi iris 2500T
|
||||
sgi iris 3130
|
||||
https://en.wikipedia.org/wiki/Sun-1
|
||||
https://en.wikipedia.org/wiki/Sun-2
|
||||
https://en.wikipedia.org/wiki/Sun-3
|
||||
https://en.wikipedia.org/wiki/HP_9000
|
||||
https://en.wikipedia.org/wiki/HP_series_80
|
||||
https://en.wikipedia.org/wiki/HP_9845C
|
||||
|
||||
note that some of these are 68000-based systems, and a few of those I want to look up for my own interests — especially since those would probably will just suffice with the GTK+ 3 port assuming a modern unix-like system can be run on them
|
||||
|
||||
IRIX {
|
||||
007-2006-120.pdf
|
||||
http://irix7.com/techpubs/007-2006-120.pdf
|
||||
|
||||
007-2006-130.pdf
|
||||
http://irix7.com/techpubs/007-2006-130.pdf
|
||||
|
||||
007-2167-005.pdf
|
||||
http://irix7.com/techpubs/007-2167-005.pdf
|
||||
|
||||
007-2167-006.pdf
|
||||
http://irix7.com/techpubs/007-2167-006.pdf
|
||||
|
||||
007-2006-080.pdf
|
||||
http://irix7.com/techpubs/007-2006-080.pdf
|
||||
|
||||
007-2006-090.pdf
|
||||
http://irix7.com/techpubs/007-2006-090.pdf
|
||||
|
||||
007-2006-100.pdf
|
||||
http://irix7.com/techpubs/007-2006-100.pdf
|
||||
|
||||
007-2167-001.pdf
|
||||
http://irix7.com/techpubs/007-2167-001.pdf
|
||||
|
||||
007-2167-002.pdf
|
||||
http://irix7.com/techpubs/007-2167-002.pdf
|
||||
|
||||
007-2167-003.pdf
|
||||
http://irix7.com/techpubs/007-2167-003.pdf
|
||||
|
||||
007-2851-001.pdf
|
||||
http://irix7.com/techpubs/007-2851-001.pdf
|
||||
|
||||
007-1472-020.pdf
|
||||
http://irix7.com/techpubs/007-1472-020.pdf
|
||||
|
||||
007-1797-020.pdf
|
||||
http://irix7.com/techpubs/007-1797-020.pdf
|
||||
|
||||
007-1797-030.pdf
|
||||
http://irix7.com/techpubs/007-1797-030.pdf
|
||||
|
||||
007-3951-001.pdf
|
||||
http://irix7.com/techpubs/007-3951-001.pdf
|
||||
} GTK+ is not an option because of no dbus, but maybe we could get away with mixing Motif and some 2D library that's in IRIX itself? but which one?...
|
|
@ -1,25 +0,0 @@
|
|||
[16:28:35] <+andlabs> https://github.com/microsoft/microsoft-ui-xaml/blob/d883cf3593912ded1a1fcc73f38768fda8ee3a45/dev/Materials/Acrylic/AcrylicBrush.cpp
|
||||
[16:28:47] <+andlabs> oh, so the acrylic effect in windows 10 uwp IS open source now after all
|
||||
[16:29:05] <+andlabs> and I bet most of it is possible in non-UWP apps with DirectComposition and Direct2D
|
||||
[16:29:46] <+andlabs> the only problem left is Get(Host)BackgroundBrush(), which are not in the open-source components and are still uWP only, and are how the actual content to blend with is grabbed
|
||||
Pietro Gagliardi, [19.05.19 00:12]
|
||||
[In reply to Pietro Gagliardi]
|
||||
https://support.microsoft.com/en-us/help/2670838/platform-update-for-windows-7-sp1-and-windows-server-2008-r2-sp1 oh, directcomposition isn't part of the windows 7 platform update, so it's a hard win8 only :|
|
||||
Pietro Gagliardi, [19.05.19 00:54]
|
||||
https://docs.microsoft.com/en-us/windows/desktop/api/dxgi1_2/nf-dxgi1_2-idxgifactory2-createswapchainforcomposition yeah, windows 7 doesn't have a flexible composition API; boo 😐
|
||||
|
||||
Pietro Gagliardi, [19.05.19 00:54]
|
||||
I guess I can use DwmEnableBlurBehindWindow on the older platforms...
|
||||
|
||||
Pietro Gagliardi, [19.05.19 00:54]
|
||||
won't work for blur-behind window-content, only blur-behind everything-underneath-the-window
|
||||
|
||||
|
||||
|
||||
https://github.com/microsoft/microsoft-ui-xaml/blob/d883cf3593912ded1a1fcc73f38768fda8ee3a45/dev/Materials/Acrylic/AcrylicBrush.cpp
|
||||
https://github.com/microsoft/WindowsCompositionSamples/issues/219
|
||||
https://docs.microsoft.com/en-us/windows/desktop/directcomp/directcomposition-portal
|
||||
https://msdn.microsoft.com/en-us/magazine/mt590968.aspx
|
||||
https://kennykerr.ca/2014/09/02/directcomposition/
|
||||
https://stackoverflow.com/questions/44000217/mimicking-acrylic-in-a-win32-app
|
||||
https://docs.microsoft.com/en-us/windows/desktop/api/dxgi1_2/nf-dxgi1_2-idxgifactory2-createswapchainforcomposition
|
|
@ -1,37 +0,0 @@
|
|||
https://marketplace.visualstudio.com/items?itemName=ms-autotest.screen-resolution-utility-task
|
||||
https://devblogs.microsoft.com/oldnewthing/20180510-00/?p=98725
|
||||
https://blogs.windows.com/buildingapps/2017/05/19/improving-high-dpi-experience-gdi-based-desktop-apps/
|
||||
https://technet.microsoft.com/en-us/evalcenter/dn469266(v=vs.90)
|
||||
https://www.windowscentral.com/how-change-high-dpi-settings-classic-apps-windows-10-april-2018-update
|
||||
https://stackoverflow.com/questions/44398075/can-dpi-scaling-be-enabled-disabled-programmatically-on-a-per-session-basis
|
||||
https://stackoverflow.com/questions/13858665/disable-dpi-awareness-for-wpf-application
|
||||
https://stackoverflow.com/questions/16571568/scaling-ui-with-dpi-change-of-non-mfc-application
|
||||
https://stackoverflow.com/questions/4075802/creating-a-dpi-aware-application
|
||||
https://kynosarges.org/WindowsDpi.html ***
|
||||
http://www.drdobbs.com/windows/coding-for-high-dpi-displays-in-windows/240168736
|
||||
https://www.tenforums.com/tutorials/5990-change-dpi-scaling-level-displays-windows-10-a.html
|
||||
https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dpi-related-apis-and-registry-settings ????
|
||||
https://stackoverflow.com/questions/35233182/how-can-i-change-windows-10-display-scaling-programmatically-using-c-sharp ****
|
||||
https://stackoverflow.com/questions/5977445/how-to-get-windows-display-settings
|
||||
https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/high-dpi-support-for-it-professionals ????
|
||||
actually ****
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/index
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/display-samples
|
||||
https://www.google.com/search?client=firefox-b-1-d&ei=M0DQXP_vNYKm_Qb_z5P4Cw&q=winapi+fake+monitor+driver&oq=winapi+fake+monitor+driver&gs_l=psy-ab.3..33i299l2j33i160.446439.447219..447312...0.0..0.173.795.0j6......0....1..gws-wiz.......0i71j33i22i29i30.LY8Gclmd9X4
|
||||
https://docs.microsoft.com/en-us/windows/desktop/gdi/the-virtual-screen
|
||||
https://www.autoitscript.com/forum/topic/134534-_desktopdimensions-details-about-the-primary-and-secondary-monitors/
|
||||
https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/um/MultiMon.h
|
||||
https://stackoverflow.com/questions/20367371/how-do-i-utilize-the-functionality-of-a-multi-monitor-setup-without-physical-har
|
||||
????
|
||||
https://stackoverflow.com/questions/16510930/creating-a-virtual-monitor-virtual-display-device ????
|
||||
https://superuser.com/questions/91786/where-can-i-find-vista-win7-virtual-display-drivers ????
|
||||
http://virtualmonitor.github.io/
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/overriding-monitor-edids ????
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/index
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/monitor-class-function-driver
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/monitor-hot-plug-detection
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/indirect-display-driver-model-overview ****
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/iddcx-objects ****
|
||||
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/iddcx/ns-iddcx-idarg_in_adapter_init ****
|
||||
https://github.com/kfroe/IndirectDisplay/blob/master/IddSampleDriver/Driver.cpp#L380-L389 ****
|
|
@ -1,34 +0,0 @@
|
|||
https://stackoverflow.com/questions/27787966/winapi-dwmapi-blur-behind-window-with-irregular-shape
|
||||
https://archive.codeplex.com/?p=glassui
|
||||
https://stackoverflow.com/questions/17246206/wpf-glass-window-with-no-border-and-no-resize-out-of-focus
|
||||
https://github.com/rust-windowing/winit/issues/260
|
||||
https://stackoverflow.com/questions/31778017/blur-behind-transparent-wpf-window
|
||||
https://web.archive.org/web/20170701081532/http://withinrafael.com/adding-the-aero-glass-blur-to-your-windows-10-apps/
|
||||
https://stackoverflow.com/questions/32335945/blur-behind-window-with-titlebar-in-windows-10-stopped-working-after-windows-up
|
||||
https://stackoverflow.com/questions/32335945/blur-behind-window-with-titlebar-in-windows-10-stopped-working-after-windows-up
|
||||
https://web.archive.org/web/20170628221023/https://blogs.windows.com/windowsexperience/2015/04/29/new-windows-10-insider-preview-build-10074-now-available/
|
||||
http://undoc.airesoft.co.uk/user32.dll/SetWindowCompositionAttribute.php
|
||||
https://gist.github.com/ysc3839/b08d2bff1c7dacde529bed1d37e85ccf
|
||||
https://gist.github.com/ethanhs/0e157e4003812e99bf5bc7cb6f73459f
|
||||
http://undoc.airesoft.co.uk/user32.dll/GetWindowCompositionAttribute.php
|
||||
https://withinrafael.com/2015/07/08/adding-the-aero-glass-blur-to-your-windows-10-apps/
|
||||
http://www.classicshell.net/forum/viewtopic.php?f=10&t=6444
|
||||
https://www.autoitscript.com/forum/topic/183488-_winapi_dwmenableblurbehindwindow-in-windows-10/
|
||||
https://stackoverflow.com/questions/31151539/native-aero-blur-without-glass-effect-on-borderless-wpf-window
|
||||
https://stackoverflow.com/questions/35736399/uwp-app-with-background-blurred-setwindowcompositionattribute
|
||||
https://www.autoitscript.com/forum/topic/189638-win10-dwm-blur-with-rounded-corners-help/
|
||||
https://www.reddit.com/r/Windows10/comments/5xa13h/is_there_any_way_i_can_make_my_command_prompt/
|
||||
https://social.msdn.microsoft.com/Forums/vstudio/en-US/ff875100-718f-473b-acf3-e2724339999f/blur-behind-option-for-wpf-controls-within-the-application?forum=wpf
|
||||
https://docs.microsoft.com/en-us/windows/win32/dwm/composition-ovw
|
||||
https://github.com/rust-windowing/winit/issues/538
|
||||
http://winclassic.boards.net/thread/39/extended-glass-borders-fix
|
||||
https://stackoverflow.com/questions/27787966/winapi-dwmapi-blur-behind-window-with-irregular-shape
|
||||
https://coldjackle.wordpress.com/2012/07/17/c-aero-glass/
|
||||
https://stackoverflow.com/questions/52735048/rounded-window-corners-with-transparent-blurred-form
|
||||
https://books.google.com/books?id=Z3g8PuyLsTMC&pg=PT149&lpg=PT149&dq=aero+glass+guide&source=bl&ots=Fg99AzeDai&sig=ACfU3U0vKunGz2-l3hykLmX6iyhMrzNv6w&hl=en&sa=X&ved=2ahUKEwjRzJz7l67kAhURYcAKHe1HDYEQ6AEwG3oECAgQAQ#v=onepage&q=aero%20glass%20guide&f=false
|
||||
https://stackoverflow.com/questions/3822609/documentation-and-api-samples-for-drawing-on-windows-aero-glass-dwm-gdi-gdi
|
||||
https://stackoverflow.com/questions/1870139/windows-aero-what-color-to-paint-to-make-glass-appear
|
||||
http://forums.codeguru.com/showthread.php?499073-Win32-Aero-glass-and-drawing-transparent-gdi-shapes
|
||||
https://archive.msdn.microsoft.com/VistaBridge/Release/ProjectReleases.aspx?ReleaseId=2230
|
||||
http://blog.delphi-jedi.net/2008/05/01/translucent-windows-with-aero/
|
||||
https://delphihaven.wordpress.com/2010/08/19/custom-drawing-on-glass-1/
|
|
@ -1,14 +0,0 @@
|
|||
http://www.danielmoth.com/Blog/Vista-Glass-Answers-And-DwmEnableBlurBehindWindow.aspx
|
||||
https://weblogs.asp.net/kennykerr/Windows-Vista-for-Developers-_1320_-Part-3-_1320_-The-Desktop-Window-Manager
|
||||
https://stackoverflow.com/questions/7981322/strategy-for-creating-a-layered-window-with-child-windows-controls
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-printwindow
|
||||
http://www.danielmoth.com/Blog/glass-nugget.aspx
|
||||
https://weblogs.asp.net/kennykerr/controls-and-the-desktop-window-manager
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-bufferedpaintinit
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-beginbufferedpaint
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-bufferedpaintsetalpha
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-endbufferedpaint
|
||||
https://docs.microsoft.com/en-us/windows/win32/api/uxtheme/nf-uxtheme-bufferedpaintuninit
|
||||
https://weblogs.asp.net/kennykerr/Windows-Vista-for-Developers-_1320_-Part-1-_1320_-Aero-Wizards
|
||||
https://weblogs.asp.net/kennykerr/Windows-Vista-for-Developers-_1320_-Part-2-_1320_-Task-Dialogs-in-Depth
|
||||
https://weblogs.asp.net/kennykerr/Windows-Vista-for-Developers-_1320_-Part-6-_1320_-The-New-File-Dialogs
|
|
@ -1,4 +0,0 @@
|
|||
uiprivExtern char *uiOpenFile(uiWindow *parent);
|
||||
uiprivExtern char *uiSaveFile(uiWindow *parent);
|
||||
uiprivExtern void uiMsgBox(uiWindow *parent, const char *title, const char *description);
|
||||
uiprivExtern void uiMsgBoxError(uiWindow *parent, const char *title, const char *description);
|
|
@ -1,17 +0,0 @@
|
|||
typedef struct uiMenuItem uiMenuItem;
|
||||
#define uiMenuItem(this) ((uiMenuItem *) (this))
|
||||
uiprivExtern void uiMenuItemEnable(uiMenuItem *m);
|
||||
uiprivExtern void uiMenuItemDisable(uiMenuItem *m);
|
||||
uiprivExtern void uiMenuItemOnClicked(uiMenuItem *m, void (*f)(uiMenuItem *sender, uiWindow *window, void *data), void *data);
|
||||
uiprivExtern int uiMenuItemChecked(uiMenuItem *m);
|
||||
uiprivExtern void uiMenuItemSetChecked(uiMenuItem *m, int checked);
|
||||
|
||||
typedef struct uiMenu uiMenu;
|
||||
#define uiMenu(this) ((uiMenu *) (this))
|
||||
uiprivExtern uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name);
|
||||
uiprivExtern uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name);
|
||||
uiprivExtern uiMenuItem *uiMenuAppendQuitItem(uiMenu *m);
|
||||
uiprivExtern uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m);
|
||||
uiprivExtern uiMenuItem *uiMenuAppendAboutItem(uiMenu *m);
|
||||
uiprivExtern void uiMenuAppendSeparator(uiMenu *m);
|
||||
uiprivExtern uiMenu *uiNewMenu(const char *name);
|
|
@ -1,148 +0,0 @@
|
|||
// 6 april 2015
|
||||
#include "uipriv_unix.h"
|
||||
|
||||
uiInitOptions uiprivOptions;
|
||||
|
||||
static GHashTable *timers;
|
||||
|
||||
const char *uiInit(uiInitOptions *o)
|
||||
{
|
||||
GError *err = NULL;
|
||||
const char *msg;
|
||||
|
||||
uiprivOptions = *o;
|
||||
if (gtk_init_with_args(NULL, NULL, NULL, NULL, NULL, &err) == FALSE) {
|
||||
msg = g_strdup(err->message);
|
||||
g_error_free(err);
|
||||
return msg;
|
||||
}
|
||||
uiprivInitAlloc();
|
||||
uiprivLoadFutures();
|
||||
timers = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct timer; // TODO get rid of forward declaration
|
||||
|
||||
static void uninitTimer(gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
uiprivFree((struct timer *) key);
|
||||
}
|
||||
|
||||
void uiUninit(void)
|
||||
{
|
||||
g_hash_table_foreach(timers, uninitTimer, NULL);
|
||||
g_hash_table_destroy(timers);
|
||||
uiprivUninitMenus();
|
||||
uiprivUninitAlloc();
|
||||
}
|
||||
|
||||
void uiFreeInitError(const char *err)
|
||||
{
|
||||
g_free((gpointer) err);
|
||||
}
|
||||
|
||||
static gboolean (*iteration)(gboolean) = NULL;
|
||||
|
||||
void uiMain(void)
|
||||
{
|
||||
iteration = gtk_main_iteration_do;
|
||||
gtk_main();
|
||||
}
|
||||
|
||||
static gboolean stepsQuit = FALSE;
|
||||
|
||||
// the only difference is we ignore the return value from gtk_main_iteration_do(), since it will always be TRUE if gtk_main() was never called
|
||||
// gtk_main_iteration_do() will still run the main loop regardless
|
||||
static gboolean stepsIteration(gboolean block)
|
||||
{
|
||||
gtk_main_iteration_do(block);
|
||||
return stepsQuit;
|
||||
}
|
||||
|
||||
void uiMainSteps(void)
|
||||
{
|
||||
iteration = stepsIteration;
|
||||
}
|
||||
|
||||
int uiMainStep(int wait)
|
||||
{
|
||||
gboolean block;
|
||||
|
||||
block = FALSE;
|
||||
if (wait)
|
||||
block = TRUE;
|
||||
return (*iteration)(block) == FALSE;
|
||||
}
|
||||
|
||||
// gtk_main_quit() may run immediately, or it may wait for other pending events; "it depends" (thanks mclasen in irc.gimp.net/#gtk+)
|
||||
// PostQuitMessage() on Windows always waits, so we must do so too
|
||||
// we'll do it by using an idle callback
|
||||
static gboolean quit(gpointer data)
|
||||
{
|
||||
if (iteration == stepsIteration)
|
||||
stepsQuit = TRUE;
|
||||
// TODO run a gtk_main() here just to do the cleanup steps of syncing the clipboard and other stuff gtk_main() does before it returns
|
||||
else
|
||||
gtk_main_quit();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void uiQuit(void)
|
||||
{
|
||||
gdk_threads_add_idle(quit, NULL);
|
||||
}
|
||||
|
||||
struct queued {
|
||||
void (*f)(void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static gboolean doqueued(gpointer data)
|
||||
{
|
||||
struct queued *q = (struct queued *) data;
|
||||
|
||||
(*(q->f))(q->data);
|
||||
g_free(q);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void uiQueueMain(void (*f)(void *data), void *data)
|
||||
{
|
||||
struct queued *q;
|
||||
|
||||
// we have to use g_new0()/g_free() because uiprivAlloc() is only safe to call on the main thread
|
||||
// for some reason it didn't affect me, but it did affect krakjoe
|
||||
q = g_new0(struct queued, 1);
|
||||
q->f = f;
|
||||
q->data = data;
|
||||
gdk_threads_add_idle(doqueued, q);
|
||||
}
|
||||
|
||||
struct timer {
|
||||
int (*f)(void *);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static gboolean doTimer(gpointer data)
|
||||
{
|
||||
struct timer *t = (struct timer *) data;
|
||||
|
||||
if (!(*(t->f))(t->data)) {
|
||||
g_hash_table_remove(timers, t);
|
||||
uiprivFree(t);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
|
||||
{
|
||||
struct timer *t;
|
||||
|
||||
t = uiprivNew(struct timer);
|
||||
t->f = f;
|
||||
t->data = data;
|
||||
g_timeout_add(milliseconds, doTimer, t);
|
||||
g_hash_table_add(timers, t);
|
||||
}
|
|
@ -1,288 +0,0 @@
|
|||
// 6 april 2015
|
||||
#import "uipriv_darwin.h"
|
||||
#import "attrstr.h"
|
||||
|
||||
static BOOL canQuit = NO;
|
||||
static NSAutoreleasePool *globalPool;
|
||||
static uiprivApplicationClass *app;
|
||||
static uiprivAppDelegate *delegate;
|
||||
|
||||
static BOOL (^isRunning)(void);
|
||||
static BOOL stepsIsRunning;
|
||||
|
||||
@implementation uiprivApplicationClass
|
||||
|
||||
- (void)sendEvent:(NSEvent *)e
|
||||
{
|
||||
if (uiprivSendAreaEvents(e) != 0)
|
||||
return;
|
||||
[super sendEvent:e];
|
||||
}
|
||||
|
||||
// NSColorPanel always sends changeColor: to the first responder regardless of whether there's a target set on it
|
||||
// we can override it here (see colorbutton.m)
|
||||
// thanks to mikeash in irc.freenode.net/#macdev for informing me this is how the first responder chain is initiated
|
||||
// it turns out NSFontManager also sends changeFont: through this; let's inhibit that here too (see fontbutton.m)
|
||||
- (BOOL)sendAction:(SEL)sel to:(id)to from:(id)from
|
||||
{
|
||||
if (uiprivColorButtonInhibitSendAction(sel, from, to))
|
||||
return NO;
|
||||
if (uiprivFontButtonInhibitSendAction(sel, from, to))
|
||||
return NO;
|
||||
return [super sendAction:sel to:to from:from];
|
||||
}
|
||||
|
||||
// likewise, NSFontManager also sends NSFontPanelValidation messages to the first responder, however it does NOT use sendAction:from:to:!
|
||||
// instead, it uses this one (thanks swillits in irc.freenode.net/#macdev)
|
||||
// we also need to override it (see fontbutton.m)
|
||||
- (id)targetForAction:(SEL)sel to:(id)to from:(id)from
|
||||
{
|
||||
id override;
|
||||
|
||||
if (uiprivFontButtonOverrideTargetForAction(sel, from, to, &override))
|
||||
return override;
|
||||
return [super targetForAction:sel to:to from:from];
|
||||
}
|
||||
|
||||
// hey look! we're overriding terminate:!
|
||||
// we're going to make sure we can go back to main() whether Cocoa likes it or not!
|
||||
// and just how are we going to do that, hm?
|
||||
// (note: this is called after applicationShouldTerminate:)
|
||||
- (void)terminate:(id)sender
|
||||
{
|
||||
// yes that's right folks: DO ABSOLUTELY NOTHING.
|
||||
// the magic is [NSApp run] will just... stop.
|
||||
|
||||
// well let's not do nothing; let's actually quit our graceful way
|
||||
NSEvent *e;
|
||||
|
||||
if (!canQuit)
|
||||
uiprivImplBug("call to [NSApp terminate:] when not ready to terminate; definitely contact andlabs");
|
||||
|
||||
[uiprivNSApp() stop:uiprivNSApp()];
|
||||
// stop: won't register until another event has passed; let's synthesize one
|
||||
e = [NSEvent otherEventWithType:NSApplicationDefined
|
||||
location:NSZeroPoint
|
||||
modifierFlags:0
|
||||
timestamp:[[NSProcessInfo processInfo] systemUptime]
|
||||
windowNumber:0
|
||||
context:[NSGraphicsContext currentContext]
|
||||
subtype:0
|
||||
data1:0
|
||||
data2:0];
|
||||
[uiprivNSApp() postEvent:e atStart:NO]; // let pending events take priority (this is what PostQuitMessage() on Windows does so we have to do it here too for parity; thanks to mikeash in irc.freenode.net/#macdev for confirming that this parameter should indeed be NO)
|
||||
|
||||
// and in case uiMainSteps() was called
|
||||
stepsIsRunning = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation uiprivAppDelegate
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// Apple docs: "Don't Use Accessor Methods in Initializer Methods and dealloc"
|
||||
[_menuManager release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
|
||||
{
|
||||
// for debugging
|
||||
NSLog(@"in applicationShouldTerminate:");
|
||||
if (uiprivShouldQuit()) {
|
||||
canQuit = YES;
|
||||
// this will call terminate:, which is the same as uiQuit()
|
||||
return NSTerminateNow;
|
||||
}
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
uiInitOptions uiprivOptions;
|
||||
|
||||
const char *uiInit(uiInitOptions *o)
|
||||
{
|
||||
@autoreleasepool {
|
||||
uiprivOptions = *o;
|
||||
app = [[uiprivApplicationClass sharedApplication] retain];
|
||||
// don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy!
|
||||
// see https://github.com/andlabs/ui/issues/6
|
||||
[uiprivNSApp() setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
delegate = [uiprivAppDelegate new];
|
||||
[uiprivNSApp() setDelegate:delegate];
|
||||
|
||||
uiprivInitAlloc();
|
||||
uiprivLoadFutures();
|
||||
uiprivLoadUndocumented();
|
||||
|
||||
// always do this so we always have an application menu
|
||||
uiprivAppDelegate().menuManager = [[uiprivMenuManager new] autorelease];
|
||||
[uiprivNSApp() setMainMenu:[uiprivAppDelegate().menuManager makeMenubar]];
|
||||
|
||||
uiprivSetupFontPanel();
|
||||
|
||||
uiprivInitUnderlineColors();
|
||||
}
|
||||
|
||||
globalPool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uiUninit(void)
|
||||
{
|
||||
if (!globalPool)
|
||||
uiprivUserBug("You must call uiInit() first!");
|
||||
[globalPool release];
|
||||
|
||||
@autoreleasepool {
|
||||
uiprivUninitUnderlineColors();
|
||||
[delegate release];
|
||||
[uiprivNSApp() setDelegate:nil];
|
||||
[app release];
|
||||
uiprivUninitAlloc();
|
||||
}
|
||||
}
|
||||
|
||||
void uiFreeInitError(const char *err)
|
||||
{
|
||||
}
|
||||
|
||||
void uiMain(void)
|
||||
{
|
||||
isRunning = ^{
|
||||
return [uiprivNSApp() isRunning];
|
||||
};
|
||||
[uiprivNSApp() run];
|
||||
}
|
||||
|
||||
void uiMainSteps(void)
|
||||
{
|
||||
// SDL does this and it seems to be necessary for the menubar to work (see #182)
|
||||
[uiprivNSApp() finishLaunching];
|
||||
isRunning = ^{
|
||||
return stepsIsRunning;
|
||||
};
|
||||
stepsIsRunning = YES;
|
||||
}
|
||||
|
||||
int uiMainStep(int wait)
|
||||
{
|
||||
uiprivNextEventArgs nea;
|
||||
|
||||
nea.mask = NSAnyEventMask;
|
||||
|
||||
// ProPuke did this in his original PR requesting this
|
||||
// I'm not sure if this will work, but I assume it will...
|
||||
nea.duration = [NSDate distantPast];
|
||||
if (wait) // but this is normal so it will work
|
||||
nea.duration = [NSDate distantFuture];
|
||||
|
||||
nea.mode = NSDefaultRunLoopMode;
|
||||
nea.dequeue = YES;
|
||||
|
||||
return uiprivMainStep(&nea, ^(NSEvent *e) {
|
||||
return NO;
|
||||
});
|
||||
}
|
||||
|
||||
// see also:
|
||||
// - http://www.cocoawithlove.com/2009/01/demystifying-nsapplication-by.html
|
||||
// - https://github.com/gnustep/gui/blob/master/Source/NSApplication.m
|
||||
int uiprivMainStep(uiprivNextEventArgs *nea, BOOL (^interceptEvent)(NSEvent *e))
|
||||
{
|
||||
NSDate *expire;
|
||||
NSEvent *e;
|
||||
NSEventType type;
|
||||
|
||||
@autoreleasepool {
|
||||
if (!isRunning())
|
||||
return 0;
|
||||
|
||||
e = [uiprivNSApp() nextEventMatchingMask:nea->mask
|
||||
untilDate:nea->duration
|
||||
inMode:nea->mode
|
||||
dequeue:nea->dequeue];
|
||||
if (e == nil)
|
||||
return 1;
|
||||
|
||||
type = [e type];
|
||||
if (!interceptEvent(e))
|
||||
[uiprivNSApp() sendEvent:e];
|
||||
[uiprivNSApp() updateWindows];
|
||||
|
||||
// GNUstep does this
|
||||
// it also updates the Services menu but there doesn't seem to be a public API for that so
|
||||
if (type != NSPeriodic && type != NSMouseMoved)
|
||||
[[uiprivNSApp() mainMenu] update];
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void uiQuit(void)
|
||||
{
|
||||
canQuit = YES;
|
||||
[uiprivNSApp() terminate:uiprivNSApp()];
|
||||
}
|
||||
|
||||
// thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this
|
||||
// LONGTERM will dispatch_get_main_queue() break after _CFRunLoopSetCurrent()?
|
||||
void uiQueueMain(void (*f)(void *data), void *data)
|
||||
{
|
||||
// dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently
|
||||
// the signature of f matches dispatch_function_t
|
||||
dispatch_async_f(dispatch_get_main_queue(), data, f);
|
||||
}
|
||||
|
||||
@interface uiprivTimerDelegate : NSObject {
|
||||
int (*f)(void *data);
|
||||
void *data;
|
||||
}
|
||||
- (id)initWithCallback:(int (*)(void *))callback data:(void *)callbackData;
|
||||
- (void)doTimer:(NSTimer *)timer;
|
||||
@end
|
||||
|
||||
@implementation uiprivTimerDelegate
|
||||
|
||||
- (id)initWithCallback:(int (*)(void *))callback data:(void *)callbackData
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self->f = callback;
|
||||
self->data = callbackData;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)doTimer:(NSTimer *)timer
|
||||
{
|
||||
if (!(*(self->f))(self->data))
|
||||
[timer invalidate];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
|
||||
{
|
||||
uiprivTimerDelegate *delegate;
|
||||
|
||||
delegate = [[uiprivTimerDelegate alloc] initWithCallback:f data:data];
|
||||
[NSTimer scheduledTimerWithTimeInterval:(milliseconds / 1000.0)
|
||||
target:delegate
|
||||
selector:@selector(doTimer:)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
[delegate release];
|
||||
}
|
||||
|
||||
// TODO figure out the best way to clean the above up in uiUninit(), if it's even necessary
|
||||
// TODO that means figure out if timers can still fire without the main loop
|
|
@ -1,9 +0,0 @@
|
|||
// 16 may 2019
|
||||
#include "uipriv.h"
|
||||
|
||||
#define sharedbitsPrefix uipriv
|
||||
#include "../sharedbits/alloc_impl.h"
|
||||
#include "../sharedbits/array_impl.h"
|
||||
#include "../sharedbits/strsafe_impl.h"
|
||||
#include "../sharedbits/strdup_impl.h"
|
||||
#undef sharedbitsPrefix
|
|
@ -0,0 +1,101 @@
|
|||
// 26 may 2015
|
||||
#include "../ui.h"
|
||||
#include "uipriv.h"
|
||||
|
||||
void uiControlDestroy(uiControl *c)
|
||||
{
|
||||
(*(c->Destroy))(c);
|
||||
}
|
||||
|
||||
uintptr_t uiControlHandle(uiControl *c)
|
||||
{
|
||||
return (*(c->Handle))(c);
|
||||
}
|
||||
|
||||
uiControl *uiControlParent(uiControl *c)
|
||||
{
|
||||
return (*(c->Parent))(c);
|
||||
}
|
||||
|
||||
void uiControlSetParent(uiControl *c, uiControl *parent)
|
||||
{
|
||||
(*(c->SetParent))(c, parent);
|
||||
}
|
||||
|
||||
int uiControlToplevel(uiControl *c)
|
||||
{
|
||||
return (*(c->Toplevel))(c);
|
||||
}
|
||||
|
||||
int uiControlVisible(uiControl *c)
|
||||
{
|
||||
return (*(c->Visible))(c);
|
||||
}
|
||||
|
||||
void uiControlShow(uiControl *c)
|
||||
{
|
||||
(*(c->Show))(c);
|
||||
}
|
||||
|
||||
void uiControlHide(uiControl *c)
|
||||
{
|
||||
(*(c->Hide))(c);
|
||||
}
|
||||
|
||||
int uiControlEnabled(uiControl *c)
|
||||
{
|
||||
return (*(c->Enabled))(c);
|
||||
}
|
||||
|
||||
void uiControlEnable(uiControl *c)
|
||||
{
|
||||
(*(c->Enable))(c);
|
||||
}
|
||||
|
||||
void uiControlDisable(uiControl *c)
|
||||
{
|
||||
(*(c->Disable))(c);
|
||||
}
|
||||
|
||||
#define uiprivControlSignature 0x7569436F
|
||||
|
||||
uiControl *uiAllocControl(size_t size, uint32_t OSsig, uint32_t typesig, const char *typenamestr)
|
||||
{
|
||||
uiControl *c;
|
||||
|
||||
c = (uiControl *) uiprivAlloc(size, typenamestr);
|
||||
c->Signature = uiprivControlSignature;
|
||||
c->OSSignature = OSsig;
|
||||
c->TypeSignature = typesig;
|
||||
return c;
|
||||
}
|
||||
|
||||
void uiFreeControl(uiControl *c)
|
||||
{
|
||||
if (uiControlParent(c) != NULL)
|
||||
uiprivUserBug("You cannot destroy a uiControl while it still has a parent. (control: %p)", c);
|
||||
uiprivFree(c);
|
||||
}
|
||||
|
||||
void uiControlVerifySetParent(uiControl *c, uiControl *parent)
|
||||
{
|
||||
uiControl *curParent;
|
||||
|
||||
if (uiControlToplevel(c))
|
||||
uiprivUserBug("You cannot give a toplevel uiControl a parent. (control: %p)", c);
|
||||
curParent = uiControlParent(c);
|
||||
if (parent != NULL && curParent != NULL)
|
||||
uiprivUserBug("You cannot give a uiControl a parent while it already has one. (control: %p; current parent: %p; new parent: %p)", c, curParent, parent);
|
||||
if (parent == NULL && curParent == NULL)
|
||||
uiprivImplBug("attempt to double unparent uiControl %p", c);
|
||||
}
|
||||
|
||||
int uiControlEnabledToUser(uiControl *c)
|
||||
{
|
||||
while (c != NULL) {
|
||||
if (!uiControlEnabled(c))
|
||||
return 0;
|
||||
c = uiControlParent(c);
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,290 +0,0 @@
|
|||
// 8 june 2019
|
||||
#include "uipriv.h"
|
||||
|
||||
struct controlType {
|
||||
uint32_t id;
|
||||
char *name;
|
||||
uiControlVtable vtable;
|
||||
uiControlOSVtable *osVtable;
|
||||
size_t implDataSize;
|
||||
};
|
||||
|
||||
static int controlTypeCmp(const void *a, const void *b)
|
||||
{
|
||||
const struct controlType *ca = (const struct controlType *) a;
|
||||
const struct controlType *cb = (const struct controlType *) b;
|
||||
|
||||
if (ca->id < cb->id)
|
||||
return -1;
|
||||
if (ca->id > cb->id)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uiControl {
|
||||
uint32_t controlID;
|
||||
uint32_t typeID;
|
||||
struct controlType *type;
|
||||
void *implData;
|
||||
uiControl *parent;
|
||||
};
|
||||
|
||||
static uiprivArray controlTypes = uiprivArrayStaticInit(struct controlType, 32, "uiControl type information");
|
||||
|
||||
#define controlTypeID UINT32_C(0x1F2E3C4D)
|
||||
|
||||
uint32_t uiControlType(void)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return 0;
|
||||
return controlTypeID;
|
||||
}
|
||||
|
||||
static uint32_t nextControlID = UINT32_C(0x80000000);
|
||||
|
||||
uint32_t uiRegisterControlType(const char *name, const uiControlVtable *vtable, const uiControlOSVtable *osVtable, size_t implDataSize)
|
||||
{
|
||||
struct controlType *ct;
|
||||
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return 0;
|
||||
if (name == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("name", uiprivFunc);
|
||||
return 0;
|
||||
}
|
||||
if (vtable == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControlVtable", uiprivFunc);
|
||||
return 0;
|
||||
}
|
||||
if (vtable->Size != sizeof (uiControlVtable)) {
|
||||
uiprivProgrammerErrorWrongStructSize(vtable->Size, "uiControlVtable", uiprivFunc);
|
||||
return 0;
|
||||
}
|
||||
#define checkMethod(method) \
|
||||
if (vtable->method == NULL) { \
|
||||
uiprivProgrammerErrorRequiredControlMethodMissing(name, "uiControlVtable", #method, uiprivFunc); \
|
||||
return 0; \
|
||||
}
|
||||
checkMethod(Init)
|
||||
checkMethod(Free)
|
||||
checkMethod(ParentChanging)
|
||||
checkMethod(ParentChanged)
|
||||
#undef checkMethod
|
||||
|
||||
if (osVtable == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControlOSVtable", uiprivFunc);
|
||||
return 0;
|
||||
}
|
||||
if (!uiprivOSVtableValid(name, osVtable, uiprivFunc))
|
||||
return 0;
|
||||
|
||||
ct = (struct controlType *) uiprivArrayAppend(&controlTypes, 1);
|
||||
ct->id = nextControlID;
|
||||
nextControlID++;
|
||||
ct->name = uiprivStrdup(name);
|
||||
ct->vtable = *vtable;
|
||||
ct->osVtable = uiprivCloneOSVtable(osVtable);
|
||||
ct->implDataSize = implDataSize;
|
||||
return ct->id;
|
||||
}
|
||||
|
||||
void *uiCheckControlType(void *c, uint32_t type)
|
||||
{
|
||||
uiControl *cc = (uiControl *) c;
|
||||
struct controlType *got, *want;
|
||||
struct controlType key;
|
||||
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return NULL;
|
||||
if (c == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControl", uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
if (cc->controlID != controlTypeID) {
|
||||
uiprivProgrammerErrorNotAControl(uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// now grab the type information for c itself
|
||||
// do this even if we were asked if this is a uiControl; we want to make absolutely sure this is a *real* uiControl
|
||||
memset(&key, 0, sizeof (struct controlType));
|
||||
key.id = cc->typeID;
|
||||
got = (struct controlType *) uiprivArrayBsearch(&controlTypes, &key, controlTypeCmp);
|
||||
if (got == NULL) {
|
||||
uiprivProgrammerErrorUnknownControlTypeUsed(cc->typeID, uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (type == controlTypeID)
|
||||
// this is a real uiControl; no need to check further
|
||||
return c;
|
||||
|
||||
// type isn't uiControlType(); make sure it is valid too
|
||||
memset(&key, 0, sizeof (struct controlType));
|
||||
key.id = type;
|
||||
want = (struct controlType *) uiprivArrayBsearch(&controlTypes, &key, controlTypeCmp);
|
||||
if (want == NULL) {
|
||||
uiprivProgrammerErrorUnknownControlTypeRequested(type, uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cc->typeID != type) {
|
||||
uiprivProgrammerErrorWrongControlType(got->name, want->name, uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
#define callVtable(method, ...) ((*(method))(__VA_ARGS__))
|
||||
|
||||
uiControl *uiNewControl(uint32_t type, void *initData)
|
||||
{
|
||||
uiControl *c;
|
||||
struct controlType *ct;
|
||||
struct controlType key;
|
||||
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return NULL;
|
||||
if (type == controlTypeID) {
|
||||
uiprivProgrammerErrorCannotCreateBaseControl(uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
memset(&key, 0, sizeof (struct controlType));
|
||||
key.id = type;
|
||||
ct = (struct controlType *) uiprivArrayBsearch(&controlTypes, &key, controlTypeCmp);
|
||||
if (ct == NULL) {
|
||||
uiprivProgrammerErrorUnknownControlTypeRequested(type, uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c = uiprivNew(uiControl);
|
||||
c->controlID = controlTypeID;
|
||||
c->typeID = type;
|
||||
c->type = ct;
|
||||
if (ct->implDataSize != 0)
|
||||
c->implData = uiprivAlloc(ct->implDataSize, "uiControl implementation data");
|
||||
if (!callVtable(c->type->vtable.Init, c, c->implData, initData)) {
|
||||
uiprivProgrammerErrorInvalidControlInitData(ct->name, uiprivFunc);
|
||||
uiprivFree(c->implData);
|
||||
uiprivFree(c);
|
||||
return NULL;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void uiControlFree(uiControl *c)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return;
|
||||
if (c == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControl", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
if (c->parent != NULL) {
|
||||
uiprivProgrammerErrorControlHasParent(uiprivFunc);
|
||||
return;
|
||||
}
|
||||
|
||||
callVtable(c->type->vtable.Free, c, c->implData);
|
||||
|
||||
uiprivFree(c->implData);
|
||||
uiprivFree(c);
|
||||
}
|
||||
|
||||
static bool parentHasCycle(uiControl *c, uiControl *parent)
|
||||
{
|
||||
// TODO remember if this is the correct way to use a local uiprivArray
|
||||
uiprivArray parents;
|
||||
size_t i;
|
||||
|
||||
if (parent == NULL)
|
||||
return false;
|
||||
if (parent == c) // easy case
|
||||
return true;
|
||||
|
||||
uiprivArrayInit(parents, uiControl *, 16, "uiControl parent list");
|
||||
// add these now, as they are counted as part of any cycles
|
||||
*((uiControl **) uiprivArrayAppend(&parents, 1)) = c;
|
||||
*((uiControl **) uiprivArrayAppend(&parents, 1)) = parent;
|
||||
for (c = parent->parent; c != NULL; c = c->parent) {
|
||||
// TODO this doesn't need to be sequential, but I don't imagine this list will ever be long enough to make it matter... yet
|
||||
for (i = 0; i < parents.len; i++)
|
||||
if (c == *uiprivArrayAt(parents, uiControl *, i)) {
|
||||
uiprivArrayFree(parents);
|
||||
return true;
|
||||
}
|
||||
// new parent; mark it as visited
|
||||
*((uiControl **) uiprivArrayAppend(&parents, 1)) = c;
|
||||
}
|
||||
|
||||
uiprivArrayFree(parents);
|
||||
return false;
|
||||
}
|
||||
|
||||
void uiControlSetParent(uiControl *c, uiControl *parent)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return;
|
||||
if (c == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControl", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->parent == NULL && parent == NULL) {
|
||||
uiprivProgrammerErrorReparenting("no", "no", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
if (c->parent != NULL && parent != NULL) {
|
||||
uiprivProgrammerErrorReparenting("a", "another", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
if (parentHasCycle(c, parent)) {
|
||||
uiprivProgrammerErrorControlParentCycle(uiprivFunc);
|
||||
return;
|
||||
}
|
||||
|
||||
callVtable(c->type->vtable.ParentChanging, c, c->implData, c->parent);
|
||||
c->parent = parent;
|
||||
callVtable(c->type->vtable.ParentChanged, c, c->implData, c->parent);
|
||||
}
|
||||
|
||||
void *uiControlImplData(uiControl *c)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return NULL;
|
||||
if (c == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControl", uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
return c->implData;
|
||||
}
|
||||
|
||||
uiControlOSVtable *uiprivControlOSVtable(uiControl *c)
|
||||
{
|
||||
return c->type->osVtable;
|
||||
}
|
||||
|
||||
uiControl *uiprivControlParent(uiControl *c)
|
||||
{
|
||||
return c->parent;
|
||||
}
|
||||
|
||||
static uiControl testHookControlWithInvalidControlMarker = {
|
||||
// use something other than 0 here to make it look like accidental real data
|
||||
.controlID = UINT32_C(0x5A5A5A5A),
|
||||
};
|
||||
|
||||
uiControl *uiprivTestHookControlWithInvalidControlMarker(void)
|
||||
{
|
||||
return &testHookControlWithInvalidControlMarker;
|
||||
}
|
||||
|
||||
static uiControl testHookControlWithInvalidType = {
|
||||
.controlID = controlTypeID,
|
||||
.typeID = 0,
|
||||
};
|
||||
|
||||
uiControl *uiprivTestHookControlWithInvalidType(void)
|
||||
{
|
||||
return &testHookControlWithInvalidType;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// 24 april 2016
|
||||
|
||||
// LONGTERM if I don't decide to remove these outright, should they be renamed uiprivTypeNameSignature? these aren't real symbols, so...
|
||||
|
||||
#define uiAreaSignature 0x41726561
|
||||
#define uiBoxSignature 0x426F784C
|
||||
#define uiButtonSignature 0x42746F6E
|
||||
#define uiCheckboxSignature 0x43686B62
|
||||
#define uiColorButtonSignature 0x436F6C42
|
||||
#define uiComboboxSignature 0x436F6D62
|
||||
#define uiDateTimePickerSignature 0x44545069
|
||||
#define uiEditableComboboxSignature 0x45644362
|
||||
#define uiEntrySignature 0x456E7472
|
||||
#define uiFontButtonSignature 0x466F6E42
|
||||
#define uiFormSignature 0x466F726D
|
||||
#define uiGridSignature 0x47726964
|
||||
#define uiGroupSignature 0x47727062
|
||||
#define uiLabelSignature 0x4C61626C
|
||||
#define uiMultilineEntrySignature 0x4D6C6E45
|
||||
#define uiProgressBarSignature 0x50426172
|
||||
#define uiRadioButtonsSignature 0x5264696F
|
||||
#define uiSeparatorSignature 0x53657061
|
||||
#define uiSliderSignature 0x536C6964
|
||||
#define uiSpinboxSignature 0x5370696E
|
||||
#define uiTabSignature 0x54616273
|
||||
#define uiTableSignature 0x5461626C
|
||||
#define uiWindowSignature 0x57696E64
|
|
@ -0,0 +1,21 @@
|
|||
// 13 may 2016
|
||||
#include "../ui.h"
|
||||
#include "uipriv.h"
|
||||
|
||||
void uiprivDoImplBug(const char *file, const char *line, const char *func, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
uiprivRealBug(file, line, func, "POSSIBLE IMPLEMENTATION BUG; CONTACT ANDLABS:\n", format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void uiprivDoUserBug(const char *file, const char *line, const char *func, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
uiprivRealBug(file, line, func, "You have a bug: ", format, ap);
|
||||
va_end(ap);
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
// 12 may 2019
|
||||
#include "uipriv.h"
|
||||
|
||||
#define internalErrorPrefix "libui internal error"
|
||||
// TODO add debugging advice?
|
||||
#define internalErrorSuffix "This likely means there is a bug in libui itself. Contact the libui authors."
|
||||
|
||||
void uiprivInternalError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[256];
|
||||
int n;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = uiprivVsnprintf(buf, 256, fmt, ap);
|
||||
va_end(ap);
|
||||
if (n < 0)
|
||||
uiprivReportError(internalErrorPrefix, "internal error string has encoding error", internalErrorSuffix, true);
|
||||
if (n >= 256)
|
||||
uiprivReportError(internalErrorPrefix, "internal error string too long", internalErrorSuffix, true);
|
||||
uiprivReportError(internalErrorPrefix, buf, internalErrorSuffix, true);
|
||||
}
|
||||
|
||||
#define programmerErrorPrefix "libui programmer error"
|
||||
// TODO add debugging advice?
|
||||
#define programmerErrorSuffix "This likely means you are using libui incorrectly. Check your source code and try again. If you have received this warning in error, contact the libui authors."
|
||||
|
||||
static uiprivTestHookReportProgrammerErrorFunc reportProgrammerErrorTestHook = NULL;
|
||||
static void *reportProgrammerErrorTestHookData = NULL;
|
||||
|
||||
void uiprivTestHookReportProgrammerError(uiprivTestHookReportProgrammerErrorFunc f, void *data)
|
||||
{
|
||||
reportProgrammerErrorTestHook = f;
|
||||
reportProgrammerErrorTestHookData = data;
|
||||
}
|
||||
|
||||
void uiprivProgrammerError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int n;
|
||||
char buf[256];
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = uiprivVsnprintf(buf, 256, fmt, ap);
|
||||
if (n < 0)
|
||||
uiprivInternalError("programmer error has encoding error");
|
||||
if (n >= 256)
|
||||
uiprivInternalError("programmer error string too long (%d)", n);
|
||||
va_end(ap);
|
||||
if (reportProgrammerErrorTestHook != NULL) {
|
||||
(*reportProgrammerErrorTestHook)(buf, reportProgrammerErrorTestHookData);
|
||||
return;
|
||||
}
|
||||
uiprivReportError(programmerErrorPrefix, buf, programmerErrorSuffix, false);
|
||||
}
|
132
common/main.c
132
common/main.c
|
@ -1,132 +0,0 @@
|
|||
// 19 april 2019
|
||||
#include "uipriv.h"
|
||||
|
||||
enum {
|
||||
stateUninitialized,
|
||||
stateBeforeMain,
|
||||
stateInMain,
|
||||
stateQuitting,
|
||||
stateAfterMain,
|
||||
stateError,
|
||||
};
|
||||
|
||||
static int state = stateUninitialized;
|
||||
|
||||
#define initialized() (state != stateUninitialized && state != stateError)
|
||||
|
||||
bool testHookInitShouldFail = false;
|
||||
|
||||
void uiprivTestHookSetInitShouldFailArtificially(bool shouldFail)
|
||||
{
|
||||
testHookInitShouldFail = shouldFail;
|
||||
}
|
||||
|
||||
bool uiInit(void *options, uiInitError *err)
|
||||
{
|
||||
if (state != stateUninitialized) {
|
||||
uiprivProgrammerErrorMultipleCalls(uiprivFunc);
|
||||
state = stateError;
|
||||
return false;
|
||||
}
|
||||
if (options != NULL) {
|
||||
uiprivProgrammerErrorBadInitOptions(uiprivFunc);
|
||||
state = stateError;
|
||||
return false;
|
||||
}
|
||||
if (err == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiInitError", uiprivFunc);
|
||||
state = stateError;
|
||||
return false;
|
||||
}
|
||||
if (err->Size != sizeof (uiInitError)) {
|
||||
uiprivProgrammerErrorWrongStructSize(err->Size, "uiInitError", uiprivFunc);
|
||||
state = stateError;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testHookInitShouldFail) {
|
||||
state = stateError;
|
||||
return uiprivInitReturnErrorf(err, "general failure");
|
||||
}
|
||||
if (!uiprivSysInit(options, err)) {
|
||||
state = stateError;
|
||||
return false;
|
||||
}
|
||||
state = stateBeforeMain;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uiprivInitReturnErrorf(uiInitError *err, const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = uiprivVsnprintf(err->Message, 256, fmt, ap);
|
||||
va_end(ap);
|
||||
if (n < 0) {
|
||||
uiprivInternalError("encoding error returning initialization error; this means something is very very wrong with libui itself");
|
||||
abort(); // TODO handle this scenario more gracefully
|
||||
}
|
||||
if (n >= 256) {
|
||||
// the formatted message is too long; truncate it
|
||||
err->Message[252] = '.';
|
||||
err->Message[253] = '.';
|
||||
err->Message[254] = '.';
|
||||
err->Message[255] = '\0';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void uiMain(void)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return;
|
||||
if (state != stateBeforeMain) {
|
||||
uiprivProgrammerErrorMultipleCalls(uiprivFunc);
|
||||
return;
|
||||
}
|
||||
state = stateInMain;
|
||||
uiprivSysMain();
|
||||
state = stateAfterMain;
|
||||
}
|
||||
|
||||
void uiQuit(void)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return;
|
||||
if (state == stateQuitting || state == stateAfterMain) {
|
||||
uiprivProgrammerErrorMultipleCalls(uiprivFunc);
|
||||
return;
|
||||
}
|
||||
if (state != stateInMain) {
|
||||
// the above handle the other states, so stateBeforeMain is what's left
|
||||
uiprivProgrammerErrorQuitBeforeMain(uiprivFunc);
|
||||
return;
|
||||
}
|
||||
state = stateQuitting;
|
||||
uiprivSysQuit();
|
||||
}
|
||||
|
||||
void uiQueueMain(void (*f)(void *data), void *data)
|
||||
{
|
||||
if (!initialized()) {
|
||||
uiprivProgrammerErrorNotInitialized(uiprivFunc);
|
||||
return;
|
||||
}
|
||||
uiprivSysQueueMain(f, data);
|
||||
}
|
||||
|
||||
bool uiprivCheckInitializedAndThreadImpl(const char *func)
|
||||
{
|
||||
// While it does seem risky to not lock this, if this changes during the execution of this function it means only that it was changed from a different thread, and since it can only change from false to true, an error will be reported anyway.
|
||||
if (!initialized()) {
|
||||
uiprivProgrammerErrorNotInitialized(func);
|
||||
return false;
|
||||
}
|
||||
if (!uiprivSysCheckThread()) {
|
||||
uiprivProgrammerErrorWrongThread(func);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -1,12 +1,17 @@
|
|||
# 23 march 2019
|
||||
|
||||
libui_sources += [
|
||||
'common/alloc.c',
|
||||
'common/controls.c',
|
||||
'common/errors.c',
|
||||
'common/main.c',
|
||||
'common/utf8.c',
|
||||
'common/window.c',
|
||||
|
||||
'common/third_party/utf.c',
|
||||
'common/attribute.c',
|
||||
'common/attrlist.c',
|
||||
'common/attrstr.c',
|
||||
'common/areaevents.c',
|
||||
'common/control.c',
|
||||
'common/debug.c',
|
||||
'common/matrix.c',
|
||||
'common/opentype.c',
|
||||
'common/shouldquit.c',
|
||||
'common/tablemodel.c',
|
||||
'common/tablevalue.c',
|
||||
'common/userbugs.c',
|
||||
'common/utf.c',
|
||||
]
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
// 2 june 2019
|
||||
|
||||
// common {
|
||||
|
||||
#define uiprivProgrammerErrorNotInitialized(func) \
|
||||
uiprivProgrammerError("attempt to call %s() before uiInit()", \
|
||||
func)
|
||||
|
||||
#define uiprivProgrammerErrorWrongThread(func) \
|
||||
uiprivProgrammerError("attempt to call %s() on a thread other than the GUI thread", \
|
||||
func)
|
||||
|
||||
#define uiprivProgrammerErrorWrongStructSize(badSize, structName, func) \
|
||||
uiprivProgrammerError("%s(): wrong size %" uiprivSizetPrintf " for %s", \
|
||||
func, badSize, structName)
|
||||
|
||||
#define uiprivProgrammerErrorIndexOutOfRange(badIndex, func) \
|
||||
uiprivProgrammerError("%s(): index %d out of range", \
|
||||
func, badIndex)
|
||||
|
||||
#define uiprivProgrammerErrorNullPointer(paramDesc, func) \
|
||||
uiprivProgrammerError("%s(): invalid null pointer for %s", \
|
||||
func, paramDesc)
|
||||
|
||||
// }
|
||||
|
||||
// main {
|
||||
|
||||
#define uiprivProgrammerErrorMultipleCalls(func) \
|
||||
uiprivProgrammerError("%s(): attempt to call more than once", func)
|
||||
|
||||
#define uiprivProgrammerErrorBadInitOptions(func) \
|
||||
uiprivProgrammerError("%s(): invalid uiInitOptions passed", func)
|
||||
|
||||
#define uiprivProgrammerErrorQuitBeforeMain(func) \
|
||||
uiprivProgrammerError("%s(): attempt to call before uiMain()", func)
|
||||
|
||||
// }
|
||||
|
||||
// controls {
|
||||
|
||||
#define uiprivProgrammerErrorRequiredControlMethodMissing(typeName, tableType, methodName, func) \
|
||||
uiprivProgrammerError("%s(): required %s method %s() missing for uiControl type %s", \
|
||||
func, tableType, methodName, typeName)
|
||||
|
||||
#define uiprivProgrammerErrorNotAControl(func) \
|
||||
uiprivProgrammerError("%s(): object passed in not a uiControl", \
|
||||
func)
|
||||
|
||||
#define uiprivProgrammerErrorUnknownControlTypeUsed(type, func) \
|
||||
uiprivProgrammerError("%s(): unknown uiControl type %" PRIu32 " found in uiControl (this is likely not a real uiControl or some data is corrupt)", \
|
||||
func, type)
|
||||
|
||||
#define uiprivProgrammerErrorUnknownControlTypeRequested(type, func) \
|
||||
uiprivProgrammerError("%s(): unknown uiControl type %" PRIu32 " requested", \
|
||||
func, type)
|
||||
|
||||
#define uiprivProgrammerErrorWrongControlType(got, want, func) \
|
||||
uiprivProgrammerError("%s(): wrong uiControl type passed: got %s, want %s", \
|
||||
func, got, want)
|
||||
|
||||
#define uiprivProgrammerErrorCannotCreateBaseControl(func) \
|
||||
uiprivProgrammerError("%s(): uiControlType() passed in when specific control type needed", \
|
||||
func)
|
||||
|
||||
#define uiprivProgrammerErrorInvalidControlInitData(type, func) \
|
||||
uiprivProgrammerError("%s(): invalid init data for %s", \
|
||||
func, type)
|
||||
|
||||
#define uiprivProgrammerErrorControlHasParent(func) \
|
||||
uiprivProgrammerError("%s(): cannot be called on a control with has a parent", \
|
||||
func)
|
||||
|
||||
#define uiprivProgrammerErrorReparenting(current, next, func) \
|
||||
uiprivProgrammerError("%s(): cannot set a control with %s parent to have %s parent", \
|
||||
func, current, next)
|
||||
|
||||
#define uiprivProgrammerErrorControlParentCycle(func) \
|
||||
uiprivProgrammerError("%s(): cannot create a parent cycle", func)
|
||||
|
||||
// }
|
||||
|
||||
// windows {
|
||||
|
||||
// TODO have any parameters, such as what the window is and what the parent is? to add func we'll need to carry that out from uiControlSetParent() (which means exposing that in the API)
|
||||
#define uiprivProgrammerErrorCannotHaveWindowsAsChildren() \
|
||||
uiprivProgrammerError("cannot set a uiWindow as the child of another uiControl")
|
||||
|
||||
// for Windows only
|
||||
#define uiprivProgrammerErrorCannotCallSetControlPosOnWindow() \
|
||||
uiprivProgrammerError("cannot call uiWindowsControlSetControlPos() on a uiWindow")
|
||||
|
||||
// }
|
|
@ -1,20 +0,0 @@
|
|||
// 26 may 2019
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// main.c
|
||||
uiprivExtern void uiprivTestHookSetInitShouldFailArtificially(bool shouldFail);
|
||||
|
||||
// errors.c
|
||||
typedef void (*uiprivTestHookReportProgrammerErrorFunc)(const char *msg, void *data);
|
||||
uiprivExtern void uiprivTestHookReportProgrammerError(uiprivTestHookReportProgrammerErrorFunc f, void *data);
|
||||
|
||||
// controls.c
|
||||
uiprivExtern uiControl *uiprivTestHookControlWithInvalidControlMarker(void);
|
||||
uiprivExtern uiControl *uiprivTestHookControlWithInvalidType(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
128
common/uipriv.h
128
common/uipriv.h
|
@ -1,94 +1,66 @@
|
|||
// 19 april 2019
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
// 6 april 2015
|
||||
// note: this file should not include ui.h, as the OS-specific ui_*.h files are included between that one and this one in the OS-specific uipriv_*.h* files
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ui.h"
|
||||
#ifdef uiprivOSHeader
|
||||
#include uiprivOSHeader
|
||||
#endif
|
||||
#include "testhooks.h"
|
||||
#include "controlsigs.h"
|
||||
#include "utf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO figure out why this is needed despite what https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2013/b0084kay(v=vs.120) says
|
||||
#ifdef _MSC_VER
|
||||
#define uiprivFunc __FUNCTION__
|
||||
#else
|
||||
#define uiprivFunc __func__
|
||||
#endif
|
||||
// OS-specific init.* or main.* files
|
||||
extern uiInitOptions uiprivOptions;
|
||||
|
||||
// TODO {
|
||||
// WHY IS THIS NEEDED?!?!?!?!!?!??!Q https://stackoverflow.com/questions/15610053/correct-printf-format-specifier-for-size-t-zu-or-iu SAYS THAT VS2013 DOES SUPPORT %zu
|
||||
// AND WHY IS MINGW AFFECTED?!?!?!?!
|
||||
// Oh and even better: the -Wno-pedantic-ms-printf stuff doesn't result in a warning about this either...
|
||||
// }
|
||||
#ifdef _WIN32
|
||||
#define uiprivSizetPrintf "Iu"
|
||||
#else
|
||||
#define uiprivSizetPrintf "zu"
|
||||
#endif
|
||||
|
||||
#include "../sharedbits/printfwarn_header.h"
|
||||
#define uiprivPrintfFunc(decl, fmtpos, appos) sharedbitsPrintfFunc(decl, fmtpos, appos)
|
||||
|
||||
// main.c
|
||||
extern bool uiprivSysInit(void *options, uiInitError *err);
|
||||
uiprivPrintfFunc(
|
||||
extern bool uiprivInitReturnErrorf(uiInitError *err, const char *fmt, ...),
|
||||
2, 3);
|
||||
extern void uiprivSysMain(void);
|
||||
extern void uiprivSysQuit(void);
|
||||
extern void uiprivSysQueueMain(void (*f)(void *data), void *data);
|
||||
extern bool uiprivCheckInitializedAndThreadImpl(const char *func);
|
||||
#define uiprivCheckInitializedAndThread() uiprivCheckInitializedAndThreadImpl(uiprivFunc)
|
||||
extern bool uiprivSysCheckThread(void);
|
||||
|
||||
// alloc.c
|
||||
#define sharedbitsPrefix uipriv
|
||||
// TODO determine if we need the ../ or not, and if not, figure out if we should use it everywhere (including ui.h) or not
|
||||
#include "../sharedbits/alloc_header.h"
|
||||
// OS-specific alloc.* files
|
||||
extern void *uiprivAlloc(size_t, const char *);
|
||||
#define uiprivNew(T) ((T *) uiprivAlloc(sizeof (T), #T))
|
||||
#include "../sharedbits/array_header.h"
|
||||
#define uiprivArrayStaticInit(T, grow, whatstr) { NULL, 0, 0, sizeof (T), grow, whatstr }
|
||||
#define uiprivArrayInit(arr, T, nGrow, what) uiprivArrayInitFull(&(arr), sizeof (T), nGrow, what)
|
||||
#define uiprivArrayFree(arr) uiprivArrayFreeFull(&(arr))
|
||||
#define uiprivArrayAt(arr, T, n) (((T *) (arr.buf)) + (n))
|
||||
#include "../sharedbits/strsafe_header.h"
|
||||
#include "../sharedbits/strdup_header.h"
|
||||
#undef sharedbitsPrefix
|
||||
extern void *uiprivRealloc(void *, size_t, const char *);
|
||||
extern void uiprivFree(void *);
|
||||
|
||||
// errors.c
|
||||
uiprivPrintfFunc(
|
||||
extern void uiprivInternalError(const char *fmt, ...),
|
||||
1, 2);
|
||||
uiprivPrintfFunc(
|
||||
extern void uiprivProgrammerError(const char *fmt, ...),
|
||||
1, 2);
|
||||
#include "programmererrors.h"
|
||||
extern void uiprivReportError(const char *prefix, const char *msg, const char *suffix, bool internal);
|
||||
// debug.c and OS-specific debug.* files
|
||||
// TODO get rid of this mess...
|
||||
// ugh, __func__ was only introduced in MSVC 2015...
|
||||
#ifdef _MSC_VER
|
||||
#define uiprivMacro__func__ __FUNCTION__
|
||||
#else
|
||||
#define uiprivMacro__func__ __func__
|
||||
#endif
|
||||
extern void uiprivRealBug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap);
|
||||
#define uiprivMacro_ns2(s) #s
|
||||
#define uiprivMacro_ns(s) uiprivMacro_ns2(s)
|
||||
extern void uiprivDoImplBug(const char *file, const char *line, const char *func, const char *format, ...);
|
||||
#define uiprivImplBug(...) uiprivDoImplBug(__FILE__, uiprivMacro_ns(__LINE__), uiprivMacro__func__, __VA_ARGS__)
|
||||
extern void uiprivDoUserBug(const char *file, const char *line, const char *func, const char *format, ...);
|
||||
#define uiprivUserBug(...) uiprivDoUserBug(__FILE__, uiprivMacro_ns(__LINE__), uiprivMacro__func__, __VA_ARGS__)
|
||||
|
||||
// controls.c
|
||||
extern bool uiprivOSVtableValid(const char *name, const uiControlOSVtable *osVtable, const char *func);
|
||||
extern uiControlOSVtable *uiprivCloneOSVtable(const uiControlOSVtable *osVtable);
|
||||
extern uiControlOSVtable *uiprivControlOSVtable(uiControl *c);
|
||||
extern uiControl *uiprivControlParent(uiControl *c);
|
||||
// shouldquit.c
|
||||
extern int uiprivShouldQuit(void);
|
||||
|
||||
// utf8.c
|
||||
extern char *uiprivSanitizeUTF8(const char *str);
|
||||
extern void uiprivFreeUTF8(char *sanitized);
|
||||
// areaevents.c
|
||||
typedef struct uiprivClickCounter uiprivClickCounter;
|
||||
// you should call Reset() to zero-initialize a new instance
|
||||
// it doesn't matter that all the non-count fields are zero: the first click will fail the curButton test straightaway, so it'll return 1 and set the rest of the structure accordingly
|
||||
struct uiprivClickCounter {
|
||||
int curButton;
|
||||
int rectX0;
|
||||
int rectY0;
|
||||
int rectX1;
|
||||
int rectY1;
|
||||
uintptr_t prevTime;
|
||||
int count;
|
||||
};
|
||||
extern int uiprivClickCounterClick(uiprivClickCounter *c, int button, int x, int y, uintptr_t time, uintptr_t maxTime, int32_t xdist, int32_t ydist);
|
||||
extern void uiprivClickCounterReset(uiprivClickCounter *);
|
||||
extern int uiprivFromScancode(uintptr_t, uiAreaKeyEvent *);
|
||||
|
||||
// window.c
|
||||
extern uint32_t uiprivSysWindowType(void);
|
||||
extern uiWindow *uiprivSysNewWindow(void);
|
||||
extern const char *uiprivSysWindowTitle(uiWindow *w);
|
||||
extern void uiprivSysWindowSetTitle(uiWindow *w, const char *title);
|
||||
extern uiControl *uiprivSysWindowChild(uiWindow *w);
|
||||
extern void uiprivSysWindowSetChild(uiWindow *w, uiControl *child);
|
||||
// matrix.c
|
||||
extern void uiprivFallbackSkew(uiDrawMatrix *, double, double, double, double);
|
||||
extern void uiprivScaleCenter(double, double, double *, double *);
|
||||
extern void uiprivFallbackTransformSize(uiDrawMatrix *, double *, double *);
|
||||
|
||||
// OS-specific text.* files
|
||||
extern int uiprivStricmp(const char *a, const char *b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
// 17 may 2020
|
||||
#include "uipriv.h"
|
||||
#include "third_party/utf.h"
|
||||
|
||||
// TODO write separate tests for this file?
|
||||
// TODO ideally this functionality should really be part of utf itself, in some form or another (for instance, via utf8SanitizedLen() + the requisite loop)
|
||||
|
||||
#define nGrow 32
|
||||
|
||||
char *uiprivSanitizeUTF8(const char *str)
|
||||
{
|
||||
size_t len;
|
||||
char *out;
|
||||
const char *s;
|
||||
size_t i;
|
||||
uint32_t rune;
|
||||
char encoded[4];
|
||||
size_t n;
|
||||
|
||||
// TODO can we even use strlen() with UTF-8 strings? or is '\0' == 0 == actual memory zero just a source code connection (and thus the last one isn't necessarily true)?
|
||||
len = strlen(str);
|
||||
out = (char *) uiprivAlloc((len + 1) * sizeof (char), "sanitized UTF-8 string");
|
||||
s = str;
|
||||
i = 0;
|
||||
while (*s != '\0') {
|
||||
s = uiprivUTF8DecodeRune(s, 0, &rune);
|
||||
n = uiprivUTF8EncodeRune(rune, encoded);
|
||||
if ((i + n) >= len) {
|
||||
out = (char *) uiprivRealloc(out, (len + 1) * sizeof (char), (len + nGrow + 1) * sizeof (char), "sanitized UTF-8 string");
|
||||
len += nGrow;
|
||||
}
|
||||
memcpy(out + i, encoded, n);
|
||||
i += n;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void uiprivFreeUTF8(char *sanitized)
|
||||
{
|
||||
uiprivFree(sanitized);
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
// 25 may 2020
|
||||
#include "uipriv.h"
|
||||
|
||||
uint32_t uiWindowType(void)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return 0;
|
||||
return uiprivSysWindowType();
|
||||
}
|
||||
|
||||
uiWindow *uiNewWindow(void)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return NULL;
|
||||
return uiprivSysNewWindow();
|
||||
}
|
||||
|
||||
const char *uiWindowTitle(uiWindow *w)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return NULL;
|
||||
if (w == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiWindow", uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
return uiprivSysWindowTitle(w);
|
||||
}
|
||||
|
||||
void uiWindowSetTitle(uiWindow *w, const char *title)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return;
|
||||
if (w == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiWindow", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
if (title == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("title", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
uiprivSysWindowSetTitle(w, title);
|
||||
}
|
||||
|
||||
uiControl *uiWindowChild(uiWindow *w)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return NULL;
|
||||
if (w == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiWindow", uiprivFunc);
|
||||
return NULL;
|
||||
}
|
||||
return uiprivSysWindowChild(w);
|
||||
}
|
||||
|
||||
void uiWindowSetChild(uiWindow *w, uiControl *child)
|
||||
{
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return;
|
||||
if (w == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiWindow", uiprivFunc);
|
||||
return;
|
||||
}
|
||||
uiprivSysWindowSetChild(w, child);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
// 8 june 2019
|
||||
#import "uipriv_darwin.h"
|
||||
|
||||
bool uiprivOSVtableValid(const char *name, const uiControlOSVtable *osVtable, const char *func)
|
||||
{
|
||||
if (osVtable->Size != sizeof (uiControlOSVtable)) {
|
||||
uiprivProgrammerErrorWrongStructSize(osVtable->Size, "uiControlOSVtable", func);
|
||||
return false;
|
||||
}
|
||||
#define checkMethod(method) \
|
||||
if (osVtable->method == NULL) { \
|
||||
uiprivProgrammerErrorRequiredControlMethodMissing(name, "uiControlOSVtable", #method, func); \
|
||||
return 0; \
|
||||
}
|
||||
checkMethod(Handle)
|
||||
return true;
|
||||
}
|
||||
|
||||
uiControlOSVtable *uiprivCloneOSVtable(const uiControlOSVtable *osVtable)
|
||||
{
|
||||
uiControlOSVtable *v2;
|
||||
|
||||
v2 = uiprivNew(uiControlOSVtable);
|
||||
*v2 = *osVtable;
|
||||
return v2;
|
||||
}
|
||||
|
||||
#define callVtable(method, ...) ((*(method))(__VA_ARGS__))
|
||||
|
||||
id uiDarwinControlHandle(uiControl *c)
|
||||
{
|
||||
uiControlOSVtable *osVtable;
|
||||
|
||||
if (!uiprivCheckInitializedAndThread())
|
||||
return nil;
|
||||
if (c == NULL) {
|
||||
uiprivProgrammerErrorNullPointer("uiControl", uiprivFunc);
|
||||
return nil;
|
||||
}
|
||||
osVtable = uiprivControlOSVtable(c);
|
||||
return callVtable(osVtable->Handle, c, uiControlImplData(c));
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// 13 may 2016
|
||||
#import "uipriv_darwin.h"
|
||||
|
||||
// LONGTERM don't halt on release builds
|
||||
|
||||
void uiprivRealBug(const char *file, const char *line, const char *func, const char *prefix, const char *format, va_list ap)
|
||||
{
|
||||
NSMutableString *str;
|
||||
NSString *formatted;
|
||||
|
||||
str = [NSMutableString new];
|
||||
[str appendString:[NSString stringWithFormat:@"[libui] %s:%s:%s() %s", file, line, func, prefix]];
|
||||
formatted = [[NSString alloc] initWithFormat:[NSString stringWithUTF8String:format] arguments:ap];
|
||||
[str appendString:formatted];
|
||||
[formatted release];
|
||||
NSLog(@"%@", str);
|
||||
[str release];
|
||||
__builtin_trap();
|
||||
}
|
331
darwin/main.m
331
darwin/main.m
|
@ -1,21 +1,92 @@
|
|||
// 20 april 2019
|
||||
// 6 april 2015
|
||||
#import "uipriv_darwin.h"
|
||||
#import "attrstr.h"
|
||||
|
||||
static BOOL canQuit = NO;
|
||||
static NSAutoreleasePool *globalPool;
|
||||
static uiprivApplicationClass *app;
|
||||
static uiprivAppDelegate *delegate;
|
||||
|
||||
static BOOL (^isRunning)(void);
|
||||
static BOOL stepsIsRunning;
|
||||
|
||||
@implementation uiprivApplicationClass
|
||||
|
||||
- (void)sendEvent:(NSEvent *)e
|
||||
{
|
||||
if (uiprivSendAreaEvents(e) != 0)
|
||||
return;
|
||||
[super sendEvent:e];
|
||||
}
|
||||
|
||||
// NSColorPanel always sends changeColor: to the first responder regardless of whether there's a target set on it
|
||||
// we can override it here (see colorbutton.m)
|
||||
// thanks to mikeash in irc.freenode.net/#macdev for informing me this is how the first responder chain is initiated
|
||||
// it turns out NSFontManager also sends changeFont: through this; let's inhibit that here too (see fontbutton.m)
|
||||
- (BOOL)sendAction:(SEL)sel to:(id)to from:(id)from
|
||||
{
|
||||
if (uiprivColorButtonInhibitSendAction(sel, from, to))
|
||||
return NO;
|
||||
if (uiprivFontButtonInhibitSendAction(sel, from, to))
|
||||
return NO;
|
||||
return [super sendAction:sel to:to from:from];
|
||||
}
|
||||
|
||||
// likewise, NSFontManager also sends NSFontPanelValidation messages to the first responder, however it does NOT use sendAction:from:to:!
|
||||
// instead, it uses this one (thanks swillits in irc.freenode.net/#macdev)
|
||||
// we also need to override it (see fontbutton.m)
|
||||
- (id)targetForAction:(SEL)sel to:(id)to from:(id)from
|
||||
{
|
||||
id override;
|
||||
|
||||
if (uiprivFontButtonOverrideTargetForAction(sel, from, to, &override))
|
||||
return override;
|
||||
return [super targetForAction:sel to:to from:from];
|
||||
}
|
||||
|
||||
// hey look! we're overriding terminate:!
|
||||
// we're going to make sure we can go back to main() whether Cocoa likes it or not!
|
||||
// and just how are we going to do that, hm?
|
||||
// (note: this is called after applicationShouldTerminate:)
|
||||
- (void)terminate:(id)sender
|
||||
{
|
||||
// yes that's right folks: DO ABSOLUTELY NOTHING.
|
||||
// the magic is [NSApp run] will just... stop.
|
||||
|
||||
// well let's not do nothing; let's actually quit our graceful way
|
||||
NSEvent *e;
|
||||
|
||||
if (!canQuit)
|
||||
uiprivImplBug("call to [NSApp terminate:] when not ready to terminate; definitely contact andlabs");
|
||||
|
||||
[uiprivNSApp() stop:uiprivNSApp()];
|
||||
// stop: won't register until another event has passed; let's synthesize one
|
||||
e = [NSEvent otherEventWithType:NSApplicationDefined
|
||||
location:NSZeroPoint
|
||||
modifierFlags:0
|
||||
timestamp:[[NSProcessInfo processInfo] systemUptime]
|
||||
windowNumber:0
|
||||
context:[NSGraphicsContext currentContext]
|
||||
subtype:0
|
||||
data1:0
|
||||
data2:0];
|
||||
[uiprivNSApp() postEvent:e atStart:NO]; // let pending events take priority (this is what PostQuitMessage() on Windows does so we have to do it here too for parity; thanks to mikeash in irc.freenode.net/#macdev for confirming that this parameter should indeed be NO)
|
||||
|
||||
// and in case uiMainSteps() was called
|
||||
stepsIsRunning = NO;
|
||||
}
|
||||
|
||||
@interface uiprivApplication : NSApplication
|
||||
@end
|
||||
|
||||
@implementation uiprivApplication
|
||||
@end
|
||||
@implementation uiprivAppDelegate
|
||||
|
||||
@interface uiprivApplicationDelegate : NSObject<NSApplicationDelegate>
|
||||
@end
|
||||
- (void)dealloc
|
||||
{
|
||||
// Apple docs: "Don't Use Accessor Methods in Initializer Methods and dealloc"
|
||||
[_menuManager release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
static uiprivApplication *uiprivApp;
|
||||
static uiprivApplicationDelegate *uiprivAppDelegate;
|
||||
|
||||
@implementation uiprivApplicationDelegate
|
||||
|
||||
#if 0
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
|
||||
{
|
||||
// for debugging
|
||||
|
@ -27,7 +98,6 @@ static uiprivApplicationDelegate *uiprivAppDelegate;
|
|||
}
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app
|
||||
{
|
||||
|
@ -36,104 +106,183 @@ static uiprivApplicationDelegate *uiprivAppDelegate;
|
|||
|
||||
@end
|
||||
|
||||
static pthread_t mainThread;
|
||||
uiInitOptions uiprivOptions;
|
||||
|
||||
bool uiprivSysInit(void *options, uiInitError *err)
|
||||
{
|
||||
uiprivApp = [uiprivApplication sharedApplication];
|
||||
if (![NSApp isKindOfClass:[uiprivApplication class]])
|
||||
// TODO verify if Info.plist (both in a proper .app bundle and embedded into a standalone binary) can override this (or if that only happens if you use NSApplicationMain() instead), and, if so, add that tidbit to this message
|
||||
return uiprivInitReturnErrorf(err, "NSApp is not of type uiprivApplication; was likely already initialized beforehand");
|
||||
|
||||
// don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy!
|
||||
// see https://github.com/andlabs/ui/issues/6
|
||||
[uiprivApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
uiprivAppDelegate = [uiprivApplicationDelegate new];
|
||||
[uiprivApp setDelegate:uiprivAppDelegate];
|
||||
|
||||
mainThread = pthread_self();
|
||||
return true;
|
||||
}
|
||||
|
||||
void uiprivSysMain(void)
|
||||
{
|
||||
[uiprivApp run];
|
||||
}
|
||||
|
||||
void uiprivSysQuit(void)
|
||||
const char *uiInit(uiInitOptions *o)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSEvent *e;
|
||||
uiprivOptions = *o;
|
||||
app = [[uiprivApplicationClass sharedApplication] retain];
|
||||
// don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy!
|
||||
// see https://github.com/andlabs/ui/issues/6
|
||||
[uiprivNSApp() setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
delegate = [uiprivAppDelegate new];
|
||||
[uiprivNSApp() setDelegate:delegate];
|
||||
|
||||
[uiprivApp stop:uiprivApp];
|
||||
// stop: won't register until another event has passed; let's synthesize one
|
||||
// TODO instead of using NSApplicationDefined, create a private event type for libui internal use only; if we can't, set up data1 and data2 so that we can intercept and discard this event if it was accidentally triggered
|
||||
e = [NSEvent otherEventWithType:NSApplicationDefined
|
||||
location:NSZeroPoint
|
||||
modifierFlags:0
|
||||
timestamp:[[NSProcessInfo processInfo] systemUptime]
|
||||
windowNumber:0
|
||||
context:[NSGraphicsContext currentContext]
|
||||
subtype:0
|
||||
data1:0
|
||||
data2:0];
|
||||
[uiprivApp postEvent:e atStart:NO]; // let pending events take priority (this is what PostQuitMessage() on Windows does so we have to do it here too for parity; thanks to mikeash in irc.freenode.net/#macdev for confirming that this parameter should indeed be NO)
|
||||
uiprivInitAlloc();
|
||||
uiprivLoadFutures();
|
||||
uiprivLoadUndocumented();
|
||||
|
||||
// always do this so we always have an application menu
|
||||
uiprivAppDelegate().menuManager = [[uiprivMenuManager new] autorelease];
|
||||
[uiprivNSApp() setMainMenu:[uiprivAppDelegate().menuManager makeMenubar]];
|
||||
|
||||
uiprivSetupFontPanel();
|
||||
|
||||
uiprivInitUnderlineColors();
|
||||
}
|
||||
|
||||
globalPool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uiUninit(void)
|
||||
{
|
||||
if (!globalPool)
|
||||
uiprivUserBug("You must call uiInit() first!");
|
||||
[globalPool release];
|
||||
|
||||
@autoreleasepool {
|
||||
uiprivUninitUnderlineColors();
|
||||
[delegate release];
|
||||
[uiprivNSApp() setDelegate:nil];
|
||||
[app release];
|
||||
uiprivUninitAlloc();
|
||||
}
|
||||
}
|
||||
|
||||
void uiFreeInitError(const char *err)
|
||||
{
|
||||
}
|
||||
|
||||
void uiMain(void)
|
||||
{
|
||||
isRunning = ^{
|
||||
return [uiprivNSApp() isRunning];
|
||||
};
|
||||
[uiprivNSApp() run];
|
||||
}
|
||||
|
||||
void uiMainSteps(void)
|
||||
{
|
||||
// SDL does this and it seems to be necessary for the menubar to work (see #182)
|
||||
[uiprivNSApp() finishLaunching];
|
||||
isRunning = ^{
|
||||
return stepsIsRunning;
|
||||
};
|
||||
stepsIsRunning = YES;
|
||||
}
|
||||
|
||||
int uiMainStep(int wait)
|
||||
{
|
||||
uiprivNextEventArgs nea;
|
||||
|
||||
nea.mask = NSAnyEventMask;
|
||||
|
||||
// ProPuke did this in his original PR requesting this
|
||||
// I'm not sure if this will work, but I assume it will...
|
||||
nea.duration = [NSDate distantPast];
|
||||
if (wait) // but this is normal so it will work
|
||||
nea.duration = [NSDate distantFuture];
|
||||
|
||||
nea.mode = NSDefaultRunLoopMode;
|
||||
nea.dequeue = YES;
|
||||
|
||||
return uiprivMainStep(&nea, ^(NSEvent *e) {
|
||||
return NO;
|
||||
});
|
||||
}
|
||||
|
||||
// see also:
|
||||
// - http://www.cocoawithlove.com/2009/01/demystifying-nsapplication-by.html
|
||||
// - https://github.com/gnustep/gui/blob/master/Source/NSApplication.m
|
||||
int uiprivMainStep(uiprivNextEventArgs *nea, BOOL (^interceptEvent)(NSEvent *e))
|
||||
{
|
||||
NSDate *expire;
|
||||
NSEvent *e;
|
||||
NSEventType type;
|
||||
|
||||
@autoreleasepool {
|
||||
if (!isRunning())
|
||||
return 0;
|
||||
|
||||
e = [uiprivNSApp() nextEventMatchingMask:nea->mask
|
||||
untilDate:nea->duration
|
||||
inMode:nea->mode
|
||||
dequeue:nea->dequeue];
|
||||
if (e == nil)
|
||||
return 1;
|
||||
|
||||
type = [e type];
|
||||
if (!interceptEvent(e))
|
||||
[uiprivNSApp() sendEvent:e];
|
||||
[uiprivNSApp() updateWindows];
|
||||
|
||||
// GNUstep does this
|
||||
// it also updates the Services menu but there doesn't seem to be a public API for that so
|
||||
if (type != NSPeriodic && type != NSMouseMoved)
|
||||
[[uiprivNSApp() mainMenu] update];
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void uiQuit(void)
|
||||
{
|
||||
canQuit = YES;
|
||||
[uiprivNSApp() terminate:uiprivNSApp()];
|
||||
}
|
||||
|
||||
// thanks to mikeash in irc.freenode.net/#macdev for suggesting the use of Grand Central Dispatch for this
|
||||
void uiprivSysQueueMain(void (*f)(void *data), void *data)
|
||||
// LONGTERM will dispatch_get_main_queue() break after _CFRunLoopSetCurrent()?
|
||||
void uiQueueMain(void (*f)(void *data), void *data)
|
||||
{
|
||||
// dispatch_get_main_queue() is a serial queue so it will not execute multiple uiQueueMain() functions concurrently
|
||||
// the signature of f matches dispatch_function_t
|
||||
dispatch_async_f(dispatch_get_main_queue(), data, f);
|
||||
}
|
||||
|
||||
bool uiprivSysCheckThread(void)
|
||||
@interface uiprivTimerDelegate : NSObject {
|
||||
int (*f)(void *data);
|
||||
void *data;
|
||||
}
|
||||
- (id)initWithCallback:(int (*)(void *))callback data:(void *)callbackData;
|
||||
- (void)doTimer:(NSTimer *)timer;
|
||||
@end
|
||||
|
||||
@implementation uiprivTimerDelegate
|
||||
|
||||
- (id)initWithCallback:(int (*)(void *))callback data:(void *)callbackData
|
||||
{
|
||||
return pthread_equal(pthread_self(), mainThread);
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self->f = callback;
|
||||
self->data = callbackData;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// Debugger() was deprecated in macOS 10.8 (as part of the larger CarbonCore deprecation), but they did not provide a replacement.
|
||||
// Though some people say inline asm, I'd rather make this work automatically everywhere.
|
||||
// Others say raise(SIGTRAP) and others still say __builtin_trap(), but I can't confirm these do what I want (some sources, including documentation, claim they either cause a core dump or send a SIGILL instead).
|
||||
// I've also heard of some new clang intrinsics, __builtin_debugtrap(), but this is totally undocumented and the original patch for this suggested it would be identical to __builtin_trap(), so...
|
||||
// Also I cannot figure out how to manually raise EXC_BREAKPOINT.
|
||||
// So that leaves us with one option: just use Debugger(), turning off the deprecation warnings.
|
||||
// Also, while we could turn off the deprecation warning temporarily in gcc >= 4.6 and any clang, I'm not sure what minimum version of gcc we need, and I'm not sure if "any clang" is even accurate.
|
||||
// So instead of juggling version macros, just turn off deprecation warnings at the bottom of this file.
|
||||
// References:
|
||||
// - https://stackoverflow.com/questions/37299/xcode-equivalent-of-asm-int-3-debugbreak-halt
|
||||
// - https://stackoverflow.com/questions/2622017/suppressing-deprecated-warnings-in-xcode
|
||||
// - https://stackoverflow.com/questions/28166565/detect-gcc-as-opposed-to-msvc-clang-with-macro
|
||||
// - https://stackoverflow.com/questions/16555585/why-pragma-gcc-diagnostic-push-pop-warning-in-gcc-c
|
||||
// - possibly others, all on stackoverflow.com (and maybe once on Apple's own forums?); I forget now
|
||||
static void debugBreak(void);
|
||||
|
||||
void uiprivReportError(const char *prefix, const char *msg, const char *suffix, bool internal)
|
||||
- (void)doTimer:(NSTimer *)timer
|
||||
{
|
||||
NSExceptionName exceptionName;
|
||||
|
||||
NSLog(@"*** %s: %s. %s", prefix, msg, suffix);
|
||||
exceptionName = NSInternalInconsistencyException;
|
||||
if (!internal)
|
||||
// TODO either find an appropriate exception for each possible message or use a custom exception name
|
||||
exceptionName = NSInvalidArgumentException;
|
||||
[NSException raise:exceptionName
|
||||
format:@"%s: %s", prefix, msg];
|
||||
debugBreak();
|
||||
if (!(*(self->f))(self->data))
|
||||
[timer invalidate];
|
||||
}
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
static void debugBreak(void)
|
||||
@end
|
||||
|
||||
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
|
||||
{
|
||||
Debugger();
|
||||
uiprivTimerDelegate *delegate;
|
||||
|
||||
delegate = [[uiprivTimerDelegate alloc] initWithCallback:f data:data];
|
||||
[NSTimer scheduledTimerWithTimeInterval:(milliseconds / 1000.0)
|
||||
target:delegate
|
||||
selector:@selector(doTimer:)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
[delegate release];
|
||||
}
|
||||
|
||||
// DO NOT ADD NEW CODE HERE. IT WILL NOT BE SUBJECT TO DEPRECATION WARNINGS.
|
||||
// I am making an exception here with Debugger(); see the large comment above.
|
||||
// TODO figure out the best way to clean the above up in uiUninit(), if it's even necessary
|
||||
// TODO that means figure out if timers can still fire without the main loop
|
||||
|
|
|
@ -1,9 +1,55 @@
|
|||
# 23 march 2019
|
||||
|
||||
libui_sources += [
|
||||
'darwin/controls.m',
|
||||
'darwin/aat.m',
|
||||
'darwin/alloc.m',
|
||||
'darwin/area.m',
|
||||
'darwin/areaevents.m',
|
||||
'darwin/attrstr.m',
|
||||
'darwin/autolayout.m',
|
||||
'darwin/box.m',
|
||||
'darwin/button.m',
|
||||
'darwin/checkbox.m',
|
||||
'darwin/colorbutton.m',
|
||||
'darwin/combobox.m',
|
||||
'darwin/control.m',
|
||||
'darwin/datetimepicker.m',
|
||||
'darwin/debug.m',
|
||||
'darwin/draw.m',
|
||||
'darwin/drawtext.m',
|
||||
'darwin/editablecombo.m',
|
||||
'darwin/entry.m',
|
||||
'darwin/fontbutton.m',
|
||||
'darwin/fontmatch.m',
|
||||
'darwin/fonttraits.m',
|
||||
'darwin/fontvariation.m',
|
||||
'darwin/form.m',
|
||||
'darwin/future.m',
|
||||
'darwin/graphemes.m',
|
||||
'darwin/grid.m',
|
||||
'darwin/group.m',
|
||||
'darwin/image.m',
|
||||
'darwin/label.m',
|
||||
'darwin/main.m',
|
||||
'darwin/map.m',
|
||||
'darwin/menu.m',
|
||||
'darwin/multilineentry.m',
|
||||
'darwin/opentype.m',
|
||||
'darwin/progressbar.m',
|
||||
'darwin/radiobuttons.m',
|
||||
'darwin/scrollview.m',
|
||||
'darwin/separator.m',
|
||||
'darwin/slider.m',
|
||||
'darwin/spinbox.m',
|
||||
'darwin/stddialogs.m',
|
||||
'darwin/tab.m',
|
||||
'darwin/table.m',
|
||||
'darwin/tablecolumn.m',
|
||||
'darwin/text.m',
|
||||
'darwin/undocumented.m',
|
||||
'darwin/util.m',
|
||||
'darwin/window.m',
|
||||
'darwin/winmoveresize.m',
|
||||
]
|
||||
|
||||
libui_deps += [
|
||||
|
|
|
@ -4,16 +4,160 @@
|
|||
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_8
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <dlfcn.h> // see future.m
|
||||
#import <pthread.h>
|
||||
#import <stdlib.h>
|
||||
#define uiprivOSHeader "../ui_darwin.h"
|
||||
#import "../ui.h"
|
||||
#import "../ui_darwin.h"
|
||||
#import "../common/uipriv.h"
|
||||
|
||||
// TODO should we rename the uiprivMk things or not
|
||||
// TODO what about renaming class wrapper functions that return the underlying class (like uiprivNewLabel())
|
||||
|
||||
#if __has_feature(objc_arc)
|
||||
#error Sorry, libui cannot be compiled with ARC.
|
||||
#endif
|
||||
|
||||
#define uiprivToNSString(str) [NSString stringWithUTF8String:(str)]
|
||||
#define uiprivFromNSString(str) [(str) UTF8String]
|
||||
|
||||
// TODO find a better place for this
|
||||
#ifndef NSAppKitVersionNumber10_9
|
||||
#define NSAppKitVersionNumber10_9 1265
|
||||
#endif
|
||||
|
||||
// map.m
|
||||
typedef struct uiprivMap uiprivMap;
|
||||
extern uiprivMap *uiprivNewMap(void);
|
||||
extern void uiprivMapDestroy(uiprivMap *m);
|
||||
extern void *uiprivMapGet(uiprivMap *m, void *key);
|
||||
extern void uiprivMapSet(uiprivMap *m, void *key, void *value);
|
||||
extern void uiprivMapDelete(uiprivMap *m, void *key);
|
||||
extern void uiprivMapWalk(uiprivMap *m, void (*f)(void *key, void *value));
|
||||
extern void uiprivMapReset(uiprivMap *m);
|
||||
|
||||
// menu.m
|
||||
@interface uiprivMenuManager : NSObject {
|
||||
uiprivMap *items;
|
||||
BOOL hasQuit;
|
||||
BOOL hasPreferences;
|
||||
BOOL hasAbout;
|
||||
}
|
||||
@property (strong) NSMenuItem *quitItem;
|
||||
@property (strong) NSMenuItem *preferencesItem;
|
||||
@property (strong) NSMenuItem *aboutItem;
|
||||
// NSMenuValidation is only informal
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item;
|
||||
- (NSMenu *)makeMenubar;
|
||||
@end
|
||||
extern void uiprivFinalizeMenus(void);
|
||||
extern void uiprivUninitMenus(void);
|
||||
|
||||
// main.m
|
||||
@interface uiprivApplicationClass : NSApplication
|
||||
@end
|
||||
// this is needed because NSApp is of type id, confusing clang
|
||||
#define uiprivNSApp() ((uiprivApplicationClass *) NSApp)
|
||||
@interface uiprivAppDelegate : NSObject<NSApplicationDelegate>
|
||||
@property (strong) uiprivMenuManager *menuManager;
|
||||
@end
|
||||
#define uiprivAppDelegate() ((uiprivAppDelegate *) [uiprivNSApp() delegate])
|
||||
typedef struct uiprivNextEventArgs uiprivNextEventArgs;
|
||||
struct uiprivNextEventArgs {
|
||||
NSEventMask mask;
|
||||
NSDate *duration;
|
||||
// LONGTERM no NSRunLoopMode?
|
||||
NSString *mode;
|
||||
BOOL dequeue;
|
||||
};
|
||||
extern int uiprivMainStep(uiprivNextEventArgs *nea, BOOL (^interceptEvent)(NSEvent *));
|
||||
|
||||
// util.m
|
||||
extern void uiprivDisableAutocorrect(NSTextView *);
|
||||
|
||||
// entry.m
|
||||
extern void uiprivFinishNewTextField(NSTextField *, BOOL);
|
||||
extern NSTextField *uiprivNewEditableTextField(void);
|
||||
|
||||
// window.m
|
||||
@interface uiprivNSWindow : NSWindow
|
||||
- (void)uiprivDoMove:(NSEvent *)initialEvent;
|
||||
- (void)uiprivDoResize:(NSEvent *)initialEvent on:(uiWindowResizeEdge)edge;
|
||||
@end
|
||||
extern uiWindow *uiprivWindowFromNSWindow(NSWindow *);
|
||||
|
||||
// alloc.m
|
||||
extern NSMutableArray *uiprivDelegates;
|
||||
extern void uiprivInitAlloc(void);
|
||||
extern void uiprivUninitAlloc(void);
|
||||
|
||||
// autolayout.m
|
||||
extern NSLayoutConstraint *uiprivMkConstraint(id view1, NSLayoutAttribute attr1, NSLayoutRelation relation, id view2, NSLayoutAttribute attr2, CGFloat multiplier, CGFloat c, NSString *desc);
|
||||
extern void uiprivJiggleViewLayout(NSView *view);
|
||||
typedef struct uiprivSingleChildConstraints uiprivSingleChildConstraints;
|
||||
struct uiprivSingleChildConstraints {
|
||||
NSLayoutConstraint *leadingConstraint;
|
||||
NSLayoutConstraint *topConstraint;
|
||||
NSLayoutConstraint *trailingConstraintGreater;
|
||||
NSLayoutConstraint *trailingConstraintEqual;
|
||||
NSLayoutConstraint *bottomConstraintGreater;
|
||||
NSLayoutConstraint *bottomConstraintEqual;
|
||||
};
|
||||
extern void uiprivSingleChildConstraintsEstablish(uiprivSingleChildConstraints *c, NSView *contentView, NSView *childView, BOOL hugsTrailing, BOOL hugsBottom, int margined, NSString *desc);
|
||||
extern void uiprivSingleChildConstraintsRemove(uiprivSingleChildConstraints *c, NSView *cv);
|
||||
extern void uiprivSingleChildConstraintsSetMargined(uiprivSingleChildConstraints *c, int margined);
|
||||
|
||||
// area.m
|
||||
extern int uiprivSendAreaEvents(NSEvent *);
|
||||
|
||||
// areaevents.m
|
||||
extern BOOL uiprivFromKeycode(unsigned short keycode, uiAreaKeyEvent *ke);
|
||||
extern BOOL uiprivKeycodeModifier(unsigned short keycode, uiModifiers *mod);
|
||||
|
||||
// draw.m
|
||||
extern uiDrawContext *uiprivDrawNewContext(CGContextRef, CGFloat);
|
||||
extern void uiprivDrawFreeContext(uiDrawContext *);
|
||||
|
||||
// fontbutton.m
|
||||
extern BOOL uiprivFontButtonInhibitSendAction(SEL sel, id from, id to);
|
||||
extern BOOL uiprivFontButtonOverrideTargetForAction(SEL sel, id from, id to, id *override);
|
||||
extern void uiprivSetupFontPanel(void);
|
||||
|
||||
// colorbutton.m
|
||||
extern BOOL uiprivColorButtonInhibitSendAction(SEL sel, id from, id to);
|
||||
|
||||
// scrollview.m
|
||||
typedef struct uiprivScrollViewCreateParams uiprivScrollViewCreateParams;
|
||||
struct uiprivScrollViewCreateParams {
|
||||
// TODO MAYBE fix these identifiers
|
||||
NSView *DocumentView;
|
||||
NSColor *BackgroundColor;
|
||||
BOOL DrawsBackground;
|
||||
BOOL Bordered;
|
||||
BOOL HScroll;
|
||||
BOOL VScroll;
|
||||
};
|
||||
typedef struct uiprivScrollViewData uiprivScrollViewData;
|
||||
extern NSScrollView *uiprivMkScrollView(uiprivScrollViewCreateParams *p, uiprivScrollViewData **dout);
|
||||
extern void uiprivScrollViewSetScrolling(NSScrollView *sv, uiprivScrollViewData *d, BOOL hscroll, BOOL vscroll);
|
||||
extern void uiprivScrollViewFreeData(NSScrollView *sv, uiprivScrollViewData *d);
|
||||
|
||||
// label.m
|
||||
extern NSTextField *uiprivNewLabel(NSString *str);
|
||||
|
||||
// image.m
|
||||
extern NSImage *uiprivImageNSImage(uiImage *);
|
||||
|
||||
// winmoveresize.m
|
||||
extern void uiprivDoManualMove(NSWindow *w, NSEvent *initialEvent);
|
||||
extern void uiprivDoManualResize(NSWindow *w, NSEvent *initialEvent, uiWindowResizeEdge edge);
|
||||
|
||||
// future.m
|
||||
extern CFStringRef *uiprivFUTURE_kCTFontOpenTypeFeatureTag;
|
||||
extern CFStringRef *uiprivFUTURE_kCTFontOpenTypeFeatureValue;
|
||||
extern CFStringRef *uiprivFUTURE_kCTBackgroundColorAttributeName;
|
||||
extern void uiprivLoadFutures(void);
|
||||
extern void uiprivFUTURE_NSLayoutConstraint_setIdentifier(NSLayoutConstraint *constraint, NSString *identifier);
|
||||
extern BOOL uiprivFUTURE_NSWindow_performWindowDragWithEvent(NSWindow *w, NSEvent *initialEvent);
|
||||
|
||||
// undocumented.m
|
||||
extern CFStringRef uiprivUNDOC_kCTFontPreferredSubFamilyNameKey;
|
||||
extern CFStringRef uiprivUNDOC_kCTFontPreferredFamilyNameKey;
|
||||
extern void uiprivLoadUndocumented(void);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue