Merging r48826 through r48828 from trunk into soc-2011-tomato
This commit is contained in:
@@ -93,9 +93,12 @@ GHOST_SystemX11(
|
||||
abort(); //was return before, but this would just mean it will crash later
|
||||
}
|
||||
|
||||
/* Open a connection to the X input manager */
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
|
||||
/* note -- don't open connection to XIM server here, because the locale
|
||||
* has to be set before opening the connection but setlocale() has not
|
||||
* been called yet. the connection will be opened after entering
|
||||
* the event loop. */
|
||||
m_xim = NULL;
|
||||
#endif
|
||||
|
||||
m_delete_window_atom
|
||||
@@ -273,6 +276,35 @@ createWindow(
|
||||
return window;
|
||||
}
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
static void destroyIMCallback(XIM xim, XPointer ptr, XPointer data)
|
||||
{
|
||||
GHOST_PRINT("XIM server died\n");
|
||||
|
||||
if (ptr)
|
||||
*(XIM *)ptr = NULL;
|
||||
}
|
||||
|
||||
bool GHOST_SystemX11::openX11_IM()
|
||||
{
|
||||
if (!m_display)
|
||||
return false;
|
||||
|
||||
/* set locale modifiers such as "@im=ibus" specified by XMODIFIERS */
|
||||
XSetLocaleModifiers("");
|
||||
|
||||
m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
|
||||
if (!m_xim)
|
||||
return false;
|
||||
|
||||
XIMCallback destroy;
|
||||
destroy.callback = (XIMProc)destroyIMCallback;
|
||||
destroy.client_data = (XPointer)&m_xim;
|
||||
XSetIMValues(m_xim, XNDestroyCallback, &destroy, NULL);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
GHOST_WindowX11 *
|
||||
GHOST_SystemX11::
|
||||
findGhostWindow(
|
||||
@@ -408,6 +440,38 @@ processEvents(
|
||||
while (XPending(m_display)) {
|
||||
XEvent xevent;
|
||||
XNextEvent(m_display, &xevent);
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
/* open connection to XIM server and create input context (XIC)
|
||||
* when receiving the first FocusIn or KeyPress event after startup,
|
||||
* or recover XIM and XIC when the XIM server has been restarted */
|
||||
if (xevent.type == FocusIn || xevent.type == KeyPress) {
|
||||
if (!m_xim && openX11_IM()) {
|
||||
GHOST_PRINT("Connected to XIM server\n");
|
||||
}
|
||||
|
||||
if (m_xim) {
|
||||
GHOST_WindowX11 * window = findGhostWindow(xevent.xany.window);
|
||||
if (window && !window->getX11_XIC() && window->createX11_XIC()) {
|
||||
GHOST_PRINT("XIM input context created\n");
|
||||
if (xevent.type == KeyPress)
|
||||
/* we can assume the window has input focus
|
||||
* here, because key events are received only
|
||||
* when the window is focused. */
|
||||
XSetICFocus(window->getX11_XIC());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* dispatch event to XIM server */
|
||||
if ((XFilterEvent(&xevent, (Window)NULL) == True) && (xevent.type != KeyRelease)) {
|
||||
/* do nothing now, the event is consumed by XIM.
|
||||
* however, KeyRelease event should be processed
|
||||
* here, otherwise modifiers remain activated. */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
processEvent(&xevent);
|
||||
anyProcessed = true;
|
||||
}
|
||||
@@ -535,7 +599,19 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
XKeyEvent *xke = &(xe->xkey);
|
||||
KeySym key_sym = XLookupKeysym(xke, 0);
|
||||
char ascii;
|
||||
char utf8_buf[6]; /* 6 is enough for a utf8 char */
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
/* utf8_array[] is initial buffer used for Xutf8LookupString().
|
||||
* if the length of the utf8 string exceeds this array, allocate
|
||||
* another memory area and call Xutf8LookupString() again.
|
||||
* the last 5 bytes are used to avoid segfault that might happen
|
||||
* at the end of this buffer when the constructor of GHOST_EventKey
|
||||
* reads 6 bytes regardless of the effective data length. */
|
||||
char utf8_array[16 * 6 + 5]; /* 16 utf8 characters */
|
||||
char *utf8_buf = utf8_array;
|
||||
int len = 1; /* at least one null character will be stored */
|
||||
#else
|
||||
char *utf8_buf = NULL;
|
||||
#endif
|
||||
|
||||
GHOST_TKey gkey = convertXKey(key_sym);
|
||||
GHOST_TEventType type = (xke->type == KeyPress) ?
|
||||
@@ -547,15 +623,20 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
/* getting unicode on key-up events gives XLookupNone status */
|
||||
if (xke->type == KeyPress) {
|
||||
XIC xic = window->getX11_XIC();
|
||||
if (xic && xke->type == KeyPress) {
|
||||
Status status;
|
||||
int len;
|
||||
|
||||
/* use utf8 because its not locale depentant, from xorg docs */
|
||||
if (!(len = Xutf8LookupString(window->getX11_XIC(), xke, utf8_buf, sizeof(utf8_buf), &key_sym, &status))) {
|
||||
if (!(len = Xutf8LookupString(xic, xke, utf8_buf, sizeof(utf8_array) - 5, &key_sym, &status))) {
|
||||
utf8_buf[0] = '\0';
|
||||
}
|
||||
|
||||
if (status == XBufferOverflow) {
|
||||
utf8_buf = (char *) malloc(len + 5);
|
||||
len = Xutf8LookupString(xic, xke, utf8_buf, len, &key_sym, &status);
|
||||
}
|
||||
|
||||
if ((status == XLookupChars || status == XLookupBoth)) {
|
||||
if ((unsigned char)utf8_buf[0] >= 32) { /* not an ascii control character */
|
||||
/* do nothing for now, this is valid utf8 */
|
||||
@@ -571,19 +652,16 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
else {
|
||||
printf("Bad keycode lookup. Keysym 0x%x Status: %s\n",
|
||||
(unsigned int) key_sym,
|
||||
(status == XBufferOverflow ? "BufferOverflow" :
|
||||
status == XLookupNone ? "XLookupNone" :
|
||||
(status == XLookupNone ? "XLookupNone" :
|
||||
status == XLookupKeySym ? "XLookupKeySym" :
|
||||
"Unknown status"));
|
||||
|
||||
printf("'%.*s' %p %p\n", len, utf8_buf, window->getX11_XIC(), m_xim);
|
||||
printf("'%.*s' %p %p\n", len, utf8_buf, xic, m_xim);
|
||||
}
|
||||
}
|
||||
else {
|
||||
utf8_buf[0] = '\0';
|
||||
}
|
||||
#else
|
||||
utf8_buf[0] = '\0';
|
||||
#endif
|
||||
|
||||
g_event = new
|
||||
@@ -595,6 +673,42 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
ascii,
|
||||
utf8_buf
|
||||
);
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
/* when using IM for some languages such as Japanese,
|
||||
* one event inserts multiple utf8 characters */
|
||||
if (xic && xke->type == KeyPress) {
|
||||
unsigned char c;
|
||||
int i = 0;
|
||||
while (1) {
|
||||
/* search character boundary */
|
||||
if ((unsigned char)utf8_buf[i++] > 0x7f) {
|
||||
for (; i < len; ++i) {
|
||||
c = utf8_buf[i];
|
||||
if (c < 0x80 || c > 0xbf) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= len) break;
|
||||
|
||||
/* enqueue previous character */
|
||||
pushEvent(g_event);
|
||||
|
||||
g_event = new
|
||||
GHOST_EventKey(
|
||||
getMilliSeconds(),
|
||||
type,
|
||||
window,
|
||||
gkey,
|
||||
'\0',
|
||||
&utf8_buf[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (utf8_buf != utf8_array)
|
||||
free(utf8_buf);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -675,6 +789,16 @@ GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
GHOST_TEventType gtype = (xfe.type == FocusIn) ?
|
||||
GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
XIC xic = window->getX11_XIC();
|
||||
if (xic) {
|
||||
if (xe->type == FocusIn)
|
||||
XSetICFocus(xic);
|
||||
else
|
||||
XUnsetICFocus(xic);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_event = new
|
||||
GHOST_Event(
|
||||
getMilliSeconds(),
|
||||
|
||||
@@ -309,6 +309,10 @@ private:
|
||||
* X11 window xwind
|
||||
*/
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
bool openX11_IM();
|
||||
#endif
|
||||
|
||||
GHOST_WindowX11 *
|
||||
findGhostWindow(
|
||||
Window xwind
|
||||
|
||||
@@ -401,10 +401,7 @@ GHOST_WindowX11(
|
||||
}
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
m_xic = XCreateIC(m_system->getX11_XIM(), XNClientWindow, m_window, XNFocusWindow, m_window,
|
||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||
XNResourceName, GHOST_X11_RES_NAME, XNResourceClass,
|
||||
GHOST_X11_RES_CLASS, NULL);
|
||||
m_xic = NULL;
|
||||
#endif
|
||||
|
||||
// Set the window icon
|
||||
@@ -478,6 +475,47 @@ GHOST_WindowX11(
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
static void destroyICCallback(XIC xic, XPointer ptr, XPointer data)
|
||||
{
|
||||
GHOST_PRINT("XIM input context destroyed\n");
|
||||
|
||||
if (ptr) {
|
||||
*(XIC *)ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool GHOST_WindowX11::createX11_XIC()
|
||||
{
|
||||
XIM xim = m_system->getX11_XIM();
|
||||
if (!xim)
|
||||
return false;
|
||||
|
||||
XICCallback destroy;
|
||||
destroy.callback = (XICProc)destroyICCallback;
|
||||
destroy.client_data = (XPointer)&m_xic;
|
||||
m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
|
||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||
XNResourceName, GHOST_X11_RES_NAME,
|
||||
XNResourceClass, GHOST_X11_RES_CLASS,
|
||||
XNDestroyCallback, &destroy,
|
||||
NULL);
|
||||
if (!m_xic)
|
||||
return false;
|
||||
|
||||
unsigned long fevent;
|
||||
XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
|
||||
XSelectInput(m_display, m_window,
|
||||
ExposureMask | StructureNotifyMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
EnterWindowMask | LeaveWindowMask |
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
PointerMotionMask | FocusChangeMask |
|
||||
PropertyChangeMask | fevent);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_X11_XINPUT
|
||||
/*
|
||||
* Dummy function to get around IO Handler exiting if device invalid
|
||||
|
||||
@@ -234,6 +234,8 @@ public:
|
||||
XIC getX11_XIC() {
|
||||
return m_xic;
|
||||
}
|
||||
|
||||
bool createX11_XIC();
|
||||
#endif
|
||||
|
||||
#ifdef WITH_XDND
|
||||
|
||||
@@ -678,26 +678,36 @@ class CLIP_PT_mask_layers(Panel):
|
||||
|
||||
sc = context.space_data
|
||||
mask = sc.mask
|
||||
active_layer = mask.layers.active
|
||||
|
||||
rows = 5 if active_layer else 2
|
||||
|
||||
row = layout.row()
|
||||
row.template_list(mask, "layers",
|
||||
mask, "active_layer_index", rows=3)
|
||||
mask, "active_layer_index", rows=rows)
|
||||
|
||||
sub = row.column(align=True)
|
||||
|
||||
sub.operator("mask.layer_new", icon='ZOOMIN', text="")
|
||||
sub.operator("mask.layer_remove", icon='ZOOMOUT', text="")
|
||||
|
||||
active = mask.layers.active
|
||||
if active:
|
||||
layout.prop(active, "name")
|
||||
if active_layer:
|
||||
sub.separator()
|
||||
|
||||
props = sub.operator("mask.layer_move", icon='TRIA_UP', text="")
|
||||
props.direction = 'UP'
|
||||
|
||||
props = sub.operator("mask.layer_move", icon='TRIA_DOWN', text="")
|
||||
props.direction = 'DOWN'
|
||||
|
||||
layout.prop(active_layer, "name")
|
||||
|
||||
# blending
|
||||
row = layout.row(align=True)
|
||||
row.prop(active, "alpha")
|
||||
row.prop(active, "invert", text="", icon='IMAGE_ALPHA')
|
||||
row.prop(active_layer, "alpha")
|
||||
row.prop(active_layer, "invert", text="", icon='IMAGE_ALPHA')
|
||||
|
||||
layout.prop(active, "blend")
|
||||
layout.prop(active_layer, "blend")
|
||||
|
||||
|
||||
class CLIP_PT_active_mask_spline(Panel):
|
||||
|
||||
@@ -238,6 +238,9 @@ void ED_operatortypes_mask(void)
|
||||
WM_operatortype_append(MASK_OT_shape_key_clear);
|
||||
WM_operatortype_append(MASK_OT_shape_key_feather_reset);
|
||||
WM_operatortype_append(MASK_OT_shape_key_rekey);
|
||||
|
||||
/* layers */
|
||||
WM_operatortype_append(MASK_OT_layer_move);
|
||||
}
|
||||
|
||||
void ED_keymap_mask(wmKeyConfig *keyconf)
|
||||
|
||||
@@ -70,6 +70,8 @@ struct MaskSplinePoint *ED_mask_point_find_nearest(
|
||||
struct MaskLayer **masklay_r, struct MaskSpline **spline_r, int *is_handle_r,
|
||||
float *score);
|
||||
|
||||
void MASK_OT_layer_move(struct wmOperatorType *ot);
|
||||
|
||||
/* mask_relationships.c */
|
||||
void MASK_OT_parent_set(struct wmOperatorType *ot);
|
||||
void MASK_OT_parent_clear(struct wmOperatorType *ot);
|
||||
|
||||
@@ -1341,3 +1341,74 @@ void MASK_OT_feather_weight_clear(wmOperatorType *ot)
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/******************** move mask layer operator *********************/
|
||||
|
||||
static int mask_layer_move_poll(bContext *C)
|
||||
{
|
||||
if (ED_maskedit_mask_poll(C)) {
|
||||
Mask *mask = CTX_data_edit_mask(C);
|
||||
|
||||
return mask->masklay_tot > 0;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int mask_layer_move_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Mask *mask = CTX_data_edit_mask(C);
|
||||
MaskLayer *mask_layer = BLI_findlink(&mask->masklayers, mask->masklay_act);
|
||||
MaskLayer *mask_layer_other;
|
||||
int direction = RNA_enum_get(op->ptr, "direction");
|
||||
|
||||
if (!mask_layer)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (direction == -1) {
|
||||
mask_layer_other = mask_layer->prev;
|
||||
|
||||
if (!mask_layer_other)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
BLI_remlink(&mask->masklayers, mask_layer);
|
||||
BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer);
|
||||
mask->masklay_act--;
|
||||
}
|
||||
else if (direction == 1) {
|
||||
mask_layer_other = mask_layer->next;
|
||||
|
||||
if (!mask_layer_other)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
BLI_remlink(&mask->masklayers, mask_layer);
|
||||
BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer);
|
||||
mask->masklay_act++;
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MASK_OT_layer_move(wmOperatorType *ot)
|
||||
{
|
||||
static EnumPropertyItem direction_items[] = {
|
||||
{-1, "UP", 0, "Up", ""},
|
||||
{1, "DOWN", 0, "Down", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Move Layer";
|
||||
ot->description = "Move the active layer up/down in the list";
|
||||
ot->idname = "MASK_OT_layer_move";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = mask_layer_move_exec;
|
||||
ot->poll = mask_layer_move_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user