mirror of
https://github.com/RaySollium99/libpicofe.git
synced 2025-09-04 22:47:44 -04:00
xenv: add minimize functionality
git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@948 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
c7b78b94e9
commit
477ba3f2ec
2 changed files with 149 additions and 13 deletions
159
linux/xenv.c
159
linux/xenv.c
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
struct xstuff {
|
struct xstuff {
|
||||||
Display *display;
|
Display *display;
|
||||||
|
Window window;
|
||||||
FPTR(XCreateBitmapFromData);
|
FPTR(XCreateBitmapFromData);
|
||||||
FPTR(XCreatePixmapCursor);
|
FPTR(XCreatePixmapCursor);
|
||||||
FPTR(XFreePixmap);
|
FPTR(XFreePixmap);
|
||||||
|
@ -50,11 +51,17 @@ struct xstuff {
|
||||||
FPTR(XMapWindow);
|
FPTR(XMapWindow);
|
||||||
FPTR(XNextEvent);
|
FPTR(XNextEvent);
|
||||||
FPTR(XCheckTypedEvent);
|
FPTR(XCheckTypedEvent);
|
||||||
FPTR(XUnmapWindow);
|
FPTR(XWithdrawWindow);
|
||||||
FPTR(XGrabKeyboard);
|
FPTR(XGrabKeyboard);
|
||||||
FPTR(XPending);
|
FPTR(XPending);
|
||||||
FPTR(XLookupKeysym);
|
FPTR(XLookupKeysym);
|
||||||
FPTR(XkbSetDetectableAutoRepeat);
|
FPTR(XkbSetDetectableAutoRepeat);
|
||||||
|
FPTR(XStoreName);
|
||||||
|
FPTR(XIconifyWindow);
|
||||||
|
FPTR(XMoveResizeWindow);
|
||||||
|
FPTR(XInternAtom);
|
||||||
|
FPTR(XSetWMHints);
|
||||||
|
FPTR(XSync);
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct xstuff g_xstuff;
|
static struct xstuff g_xstuff;
|
||||||
|
@ -74,7 +81,7 @@ static Cursor transparent_cursor(struct xstuff *xf, Display *display, Window win
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x11h_init(void)
|
static int x11h_init(const char *window_title)
|
||||||
{
|
{
|
||||||
unsigned int display_width, display_height;
|
unsigned int display_width, display_height;
|
||||||
Display *display;
|
Display *display;
|
||||||
|
@ -102,11 +109,17 @@ static int x11h_init(void)
|
||||||
FPTR_LINK(g_xstuff, x11lib, XMapWindow);
|
FPTR_LINK(g_xstuff, x11lib, XMapWindow);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XNextEvent);
|
FPTR_LINK(g_xstuff, x11lib, XNextEvent);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XCheckTypedEvent);
|
FPTR_LINK(g_xstuff, x11lib, XCheckTypedEvent);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XUnmapWindow);
|
FPTR_LINK(g_xstuff, x11lib, XWithdrawWindow);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XGrabKeyboard);
|
FPTR_LINK(g_xstuff, x11lib, XGrabKeyboard);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XPending);
|
FPTR_LINK(g_xstuff, x11lib, XPending);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XLookupKeysym);
|
FPTR_LINK(g_xstuff, x11lib, XLookupKeysym);
|
||||||
FPTR_LINK(g_xstuff, x11lib, XkbSetDetectableAutoRepeat);
|
FPTR_LINK(g_xstuff, x11lib, XkbSetDetectableAutoRepeat);
|
||||||
|
FPTR_LINK(g_xstuff, x11lib, XStoreName);
|
||||||
|
FPTR_LINK(g_xstuff, x11lib, XIconifyWindow);
|
||||||
|
FPTR_LINK(g_xstuff, x11lib, XMoveResizeWindow);
|
||||||
|
FPTR_LINK(g_xstuff, x11lib, XInternAtom);
|
||||||
|
FPTR_LINK(g_xstuff, x11lib, XSetWMHints);
|
||||||
|
FPTR_LINK(g_xstuff, x11lib, XSync);
|
||||||
|
|
||||||
//XInitThreads();
|
//XInitThreads();
|
||||||
|
|
||||||
|
@ -132,23 +145,26 @@ static int x11h_init(void)
|
||||||
display_height = DisplayHeight(display, screen);
|
display_height = DisplayHeight(display, screen);
|
||||||
printf(PFX "display is %dx%d\n", display_width, display_height);
|
printf(PFX "display is %dx%d\n", display_width, display_height);
|
||||||
|
|
||||||
win = g_xstuff.pXCreateSimpleWindow(display,
|
g_xstuff.window = win = g_xstuff.pXCreateSimpleWindow(display,
|
||||||
RootWindow(display, screen),
|
RootWindow(display, screen), 0, 0, display_width, display_height,
|
||||||
0, 0, display_width, display_height, 0,
|
0, BlackPixel(display, screen), BlackPixel(display, screen));
|
||||||
BlackPixel(display, screen),
|
|
||||||
BlackPixel(display, screen));
|
|
||||||
|
|
||||||
attributes.override_redirect = True;
|
attributes.override_redirect = True;
|
||||||
attributes.cursor = transparent_cursor(&g_xstuff, display, win);
|
attributes.cursor = transparent_cursor(&g_xstuff, display, win);
|
||||||
g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
|
g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
|
||||||
|
|
||||||
g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask
|
g_xstuff.pXStoreName(display, win, window_title);
|
||||||
| KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
|
g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask
|
||||||
|
| KeyPressMask | KeyReleaseMask | ButtonPressMask
|
||||||
|
| ButtonReleaseMask | PointerMotionMask | PropertyChangeMask);
|
||||||
g_xstuff.pXMapWindow(display, win);
|
g_xstuff.pXMapWindow(display, win);
|
||||||
g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||||
g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
|
g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
|
||||||
// XSetIOErrorHandler
|
// XSetIOErrorHandler
|
||||||
|
|
||||||
|
// we don't know when event dispatch will be called, so sync now
|
||||||
|
g_xstuff.pXSync(display, False);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail2:
|
fail2:
|
||||||
dlclose(x11lib);
|
dlclose(x11lib);
|
||||||
|
@ -208,6 +224,86 @@ static void x11h_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void x11h_wait_vmstate(void)
|
||||||
|
{
|
||||||
|
Atom wm_state = g_xstuff.pXInternAtom(g_xstuff.display, "WM_STATE", False);
|
||||||
|
XEvent evt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
usleep(20000);
|
||||||
|
|
||||||
|
for (i = 0; i < 20; i++) {
|
||||||
|
while (g_xstuff.pXPending(g_xstuff.display)) {
|
||||||
|
g_xstuff.pXNextEvent(g_xstuff.display, &evt);
|
||||||
|
// printf("w event %d\n", evt.type);
|
||||||
|
if (evt.type == PropertyNotify && evt.xproperty.atom == wm_state)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
usleep(200000);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, PFX "timeout waiting for wm_state change\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int x11h_minimize(void)
|
||||||
|
{
|
||||||
|
XSetWindowAttributes attributes;
|
||||||
|
Display *display = g_xstuff.display;
|
||||||
|
Window window = g_xstuff.window;
|
||||||
|
int screen = DefaultScreen(g_xstuff.display);
|
||||||
|
int display_width, display_height;
|
||||||
|
XWMHints wm_hints;
|
||||||
|
XEvent evt;
|
||||||
|
|
||||||
|
g_xstuff.pXWithdrawWindow(display, window, screen);
|
||||||
|
|
||||||
|
attributes.override_redirect = False;
|
||||||
|
g_xstuff.pXChangeWindowAttributes(display, window,
|
||||||
|
CWOverrideRedirect, &attributes);
|
||||||
|
|
||||||
|
wm_hints.flags = StateHint;
|
||||||
|
wm_hints.initial_state = IconicState;
|
||||||
|
g_xstuff.pXSetWMHints(display, window, &wm_hints);
|
||||||
|
|
||||||
|
g_xstuff.pXMapWindow(display, window);
|
||||||
|
|
||||||
|
while (g_xstuff.pXNextEvent(display, &evt) == 0)
|
||||||
|
{
|
||||||
|
// printf("m event %d\n", evt.type);
|
||||||
|
switch (evt.type)
|
||||||
|
{
|
||||||
|
case FocusIn:
|
||||||
|
goto out;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_xstuff.pXWithdrawWindow(display, window, screen);
|
||||||
|
|
||||||
|
// must wait for some magic vmstate property change before setting override_redirect
|
||||||
|
x11h_wait_vmstate();
|
||||||
|
|
||||||
|
attributes.override_redirect = True;
|
||||||
|
g_xstuff.pXChangeWindowAttributes(display, window,
|
||||||
|
CWOverrideRedirect, &attributes);
|
||||||
|
|
||||||
|
// fixup window after resize on override_redirect loss
|
||||||
|
display_width = DisplayWidth(display, screen);
|
||||||
|
display_height = DisplayHeight(display, screen);
|
||||||
|
g_xstuff.pXMoveResizeWindow(display, window, 0, 0, display_width, display_height);
|
||||||
|
|
||||||
|
g_xstuff.pXMapWindow(display, window);
|
||||||
|
g_xstuff.pXGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||||
|
g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
|
||||||
|
|
||||||
|
// we don't know when event dispatch will be called, so sync now
|
||||||
|
g_xstuff.pXSync(display, False);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct termios g_kbd_termios_saved;
|
static struct termios g_kbd_termios_saved;
|
||||||
static int g_kbdfd = -1;
|
static int g_kbdfd = -1;
|
||||||
|
|
||||||
|
@ -272,12 +368,12 @@ static void tty_end(void)
|
||||||
g_kbdfd = -1;
|
g_kbdfd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xenv_init(int *have_mouse_events)
|
int xenv_init(int *have_mouse_events, const char *window_title)
|
||||||
{
|
{
|
||||||
int have_mouse = 0;
|
int have_mouse = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = x11h_init();
|
ret = x11h_init(window_title);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
have_mouse = 1;
|
have_mouse = 1;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -309,8 +405,47 @@ int xenv_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* blocking minimize until user maximizes again */
|
||||||
|
int xenv_minimize(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (g_xstuff.display) {
|
||||||
|
xenv_update(NULL, NULL, NULL, NULL);
|
||||||
|
ret = x11h_minimize();
|
||||||
|
xenv_update(NULL, NULL, NULL, NULL);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void xenv_finish(void)
|
void xenv_finish(void)
|
||||||
{
|
{
|
||||||
// TODO: cleanup X?
|
// TODO: cleanup X?
|
||||||
tty_end();
|
tty_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int i, r, d;
|
||||||
|
|
||||||
|
xenv_init("just a test");
|
||||||
|
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
while ((r = xenv_update(&d)) > 0)
|
||||||
|
printf("%d %x %d\n", d, r, r);
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
if (i == 1)
|
||||||
|
xenv_minimize();
|
||||||
|
printf("ll %d\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("xenv_finish..\n");
|
||||||
|
xenv_finish();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
int xenv_init(int *have_mouse_events);
|
int xenv_init(int *have_mouse_events, const char *window_title);
|
||||||
|
|
||||||
/* read events from X, calling key_cb for key, mouseb_cb for mouse button
|
/* read events from X, calling key_cb for key, mouseb_cb for mouse button
|
||||||
* and mousem_cb for mouse motion events */
|
* and mousem_cb for mouse motion events */
|
||||||
|
@ -8,5 +8,6 @@ int xenv_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
|
||||||
int (*mousem_cb)(void *cb_arg, int x, int y),
|
int (*mousem_cb)(void *cb_arg, int x, int y),
|
||||||
void *cb_arg);
|
void *cb_arg);
|
||||||
|
|
||||||
|
int xenv_minimize(void);
|
||||||
void xenv_finish(void);
|
void xenv_finish(void);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue