Implemented TextField.ReadOnly() on Mac OS X. Began standardizing window class name access on Windows.
This commit is contained in:
parent
cd96f8ee2e
commit
b632fef3b1
|
@ -136,6 +136,7 @@ id newTextField(void)
|
||||||
NSTextField *t;
|
NSTextField *t;
|
||||||
|
|
||||||
t = [[NSTextField alloc] initWithFrame:NSZeroRect];
|
t = [[NSTextField alloc] initWithFrame:NSZeroRect];
|
||||||
|
[t setSelectable:YES]; // otherwise the setting is masked by the editable default of YES
|
||||||
return finishNewTextField((id) t, YES);
|
return finishNewTextField((id) t, YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +145,7 @@ id newPasswordField(void)
|
||||||
NSSecureTextField *t;
|
NSSecureTextField *t;
|
||||||
|
|
||||||
t = [[NSSecureTextField alloc] initWithFrame:NSZeroRect];
|
t = [[NSSecureTextField alloc] initWithFrame:NSZeroRect];
|
||||||
|
[t setSelectable:YES]; // otherwise the setting is masked by the editable default of YES
|
||||||
return finishNewTextField((id) t, YES);
|
return finishNewTextField((id) t, YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +186,16 @@ void textfieldCloseInvalidPopover(id popover)
|
||||||
// don't release; close does that already
|
// don't release; close does that already
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL textfieldEditable(id textfield)
|
||||||
|
{
|
||||||
|
return [toNSTextField(textfield) isEditable];
|
||||||
|
}
|
||||||
|
|
||||||
|
void textfieldSetEditable(id textfield, BOOL editable)
|
||||||
|
{
|
||||||
|
[toNSTextField(textfield) setEditable:editable];
|
||||||
|
}
|
||||||
|
|
||||||
id newLabel(void)
|
id newLabel(void)
|
||||||
{
|
{
|
||||||
NSTextField *l;
|
NSTextField *l;
|
||||||
|
|
|
@ -100,7 +100,7 @@ void paintControlBackground(HWND hwnd, HDC dc)
|
||||||
HWND parent;
|
HWND parent;
|
||||||
RECT r;
|
RECT r;
|
||||||
POINT p, pOrig;
|
POINT p, pOrig;
|
||||||
WCHAR classname[128] = L""; // more than enough to avoid collisions
|
WCHAR classname[maxClassName + 1] = L"";
|
||||||
|
|
||||||
parent = hwnd;
|
parent = hwnd;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -110,7 +110,7 @@ void paintControlBackground(HWND hwnd, HDC dc)
|
||||||
// wine sends these messages early, yay...
|
// wine sends these messages early, yay...
|
||||||
if (parent == msgwin)
|
if (parent == msgwin)
|
||||||
return;
|
return;
|
||||||
if (GetClassNameW(parent, classname, 128) == 0)
|
if (GetClassNameW(parent, classname, maxClassName) == 0)
|
||||||
xpanic("error getting name of focused window class in paintControlBackground()", GetLastError());
|
xpanic("error getting name of focused window class in paintControlBackground()", GetLastError());
|
||||||
// skip groupboxes; they're (supposed to be) transparent
|
// skip groupboxes; they're (supposed to be) transparent
|
||||||
if (_wcsicmp(classname, L"button") != 0)
|
if (_wcsicmp(classname, L"button") != 0)
|
||||||
|
|
|
@ -75,6 +75,8 @@ extern const char *textfieldText(id);
|
||||||
extern void textfieldSetText(id, char *);
|
extern void textfieldSetText(id, char *);
|
||||||
extern id textfieldOpenInvalidPopover(id, char *);
|
extern id textfieldOpenInvalidPopover(id, char *);
|
||||||
extern void textfieldCloseInvalidPopover(id);
|
extern void textfieldCloseInvalidPopover(id);
|
||||||
|
extern BOOL textfieldEditable(id);
|
||||||
|
extern void textfieldSetEditable(id, BOOL);
|
||||||
extern id newLabel(void);
|
extern id newLabel(void);
|
||||||
extern id newGroup(id);
|
extern id newGroup(id);
|
||||||
extern const char *groupText(id);
|
extern const char *groupText(id);
|
||||||
|
|
|
@ -62,6 +62,16 @@ func (t *textfield) Invalid(reason string) {
|
||||||
t.invalid = C.textfieldOpenInvalidPopover(t.id, creason)
|
t.invalid = C.textfieldOpenInvalidPopover(t.id, creason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note that the property here is editable, which is the opposite of read-only
|
||||||
|
|
||||||
|
func (t *textfield) ReadOnly() bool {
|
||||||
|
return !fromBOOL(C.textfieldEditable(t.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *textfield) SetReadOnly(readonly bool) {
|
||||||
|
C.textfieldSetEditable(t.id, toBOOL(!readonly))
|
||||||
|
}
|
||||||
|
|
||||||
//export textfieldChanged
|
//export textfieldChanged
|
||||||
func textfieldChanged(data unsafe.Pointer) {
|
func textfieldChanged(data unsafe.Pointer) {
|
||||||
t := (*textfield)(data)
|
t := (*textfield)(data)
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
#include "winapi_windows.h"
|
#include "winapi_windows.h"
|
||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
// note that this includes the terminating '\0'
|
|
||||||
// this also assumes WC_TABCONTROL is longer than areaWindowClass
|
|
||||||
#define NCLASSNAME (sizeof WC_TABCONTROL / sizeof WC_TABCONTROL[0])
|
|
||||||
|
|
||||||
void uimsgloop_area(HWND active, HWND focus, MSG *msg)
|
void uimsgloop_area(HWND active, HWND focus, MSG *msg)
|
||||||
{
|
{
|
||||||
MSG copy;
|
MSG copy;
|
||||||
|
@ -63,7 +59,7 @@ void uimsgloop(void)
|
||||||
MSG msg;
|
MSG msg;
|
||||||
int res;
|
int res;
|
||||||
HWND active, focus;
|
HWND active, focus;
|
||||||
WCHAR classchk[NCLASSNAME];
|
WCHAR classchk[maxClassName + 1];
|
||||||
BOOL dodlgmessage;
|
BOOL dodlgmessage;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -82,12 +78,9 @@ void uimsgloop(void)
|
||||||
// bit of logic involved here:
|
// bit of logic involved here:
|
||||||
// we don't want dialog messages passed into Areas, so we don't call IsDialogMessageW() there
|
// we don't want dialog messages passed into Areas, so we don't call IsDialogMessageW() there
|
||||||
// as for Tabs, we can't have both WS_TABSTOP and WS_EX_CONTROLPARENT set at the same time, so we hotswap the two styles to get the behavior we want
|
// as for Tabs, we can't have both WS_TABSTOP and WS_EX_CONTROLPARENT set at the same time, so we hotswap the two styles to get the behavior we want
|
||||||
// theoretically we could use the class atom to avoid a wcscmp()
|
|
||||||
// however, raymond chen advises against this - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx (and we're not in control of the Tab class, before you say anything)
|
|
||||||
// we could also theoretically just send msgAreaDefocuses directly, but what DefWindowProc() does to a WM_APP message is undocumented
|
|
||||||
focus = GetFocus();
|
focus = GetFocus();
|
||||||
if (focus != NULL) {
|
if (focus != NULL) {
|
||||||
if (GetClassNameW(focus, classchk, NCLASSNAME) == 0)
|
if (GetClassNameW(focus, classchk, maxClassName) == 0)
|
||||||
xpanic("error getting name of focused window class for Area check", GetLastError());
|
xpanic("error getting name of focused window class for Area check", GetLastError());
|
||||||
if (_wcsicmp(classchk, areaWindowClass) == 0) {
|
if (_wcsicmp(classchk, areaWindowClass) == 0) {
|
||||||
uimsgloop_area(active, focus, &msg);
|
uimsgloop_area(active, focus, &msg);
|
||||||
|
|
|
@ -41,6 +41,13 @@ enum {
|
||||||
msgOpenFileDone,
|
msgOpenFileDone,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// there are a number of places where we need to know what window class an arbitrary handle has
|
||||||
|
// theoretically we could use the class atom to avoid a _wcsicmp()
|
||||||
|
// however, raymond chen advises against this - http://blogs.msdn.com/b/oldnewthing/archive/2004/10/11/240744.aspx (and we're not in control of the Tab class, before you say anything)
|
||||||
|
// MSDN says 256 is the maximum length of a class name; add a few characters just to be safe (because it doesn't say whether this includes the terminating null character)
|
||||||
|
// TODO localize this to a helper function
|
||||||
|
#define maxClassName 260
|
||||||
|
|
||||||
// uitask_windows.c
|
// uitask_windows.c
|
||||||
extern void uimsgloop(void);
|
extern void uimsgloop(void);
|
||||||
extern void issue(void *);
|
extern void issue(void *);
|
||||||
|
|
Loading…
Reference in New Issue