Merging r48826 through r48828 from trunk into soc-2011-tomato

This commit is contained in:
Sergey Sharybin
2012-07-11 10:39:08 +00:00
8 changed files with 276 additions and 22 deletions

View File

@@ -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(),

View File

@@ -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

View File

@@ -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

View File

@@ -234,6 +234,8 @@ public:
XIC getX11_XIC() {
return m_xic;
}
bool createX11_XIC();
#endif
#ifdef WITH_XDND

View File

@@ -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):

View File

@@ -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)

View File

@@ -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);

View File

@@ -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");
}